# 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 +ImplSet False @@ -400,7 +400,7 @@ 264 178 53 -ImplContainer contains a number +ImplSet contains a number of implementation instances and generates output using them. @@ -510,7 +510,7 @@ 384 202 83 -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 @@ 496 192 68 -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 @@ 568 16 190 -38 +53 ImplBase and ReaderBase comprise -the ConE plug-in interface +the ConE plug-in interface for +implementations. clMaroon $00B9FFFF -569,139;645,53 +569,141;638,68 D2lNkx9zqkGIrORCziB2MwAA KeRNcoIQK0KSH6AGF9UzjAAA clMaroon $00B9FFFF -727,152;672,53 +726,152;677,68 D2lNkx9zqkGIrORCziB2MwAA 2t2cUMI4f0SGZ3fMzCfV2QAA clMaroon $00DFFFFF -20 +24 12 167 38 -ImplContainer is used when +ImplSet is used when generating output using ConE. clMaroon $00B9FFFF -166,148;113,49 +167,148;117,49 v84tCD/ORU6aA+sNvC8HbgAA EFzcsknNQ0O+rr8VseO9MAAA @@ -798,9 +799,9 @@ -17 +16 -ImplContainer +ImplSet NmvwO09X4Uu7xy6qNwdIDQAA 4 EFzcsknNQ0O+rr8VseO9MAAA @@ -935,11 +936,7 @@ Configuration NmvwO09X4Uu7xy6qNwdIDQAA - -Jung, Yoontae -NmvwO09X4Uu7xy6qNwdIDQAA - - + SomeImplReader NmvwO09X4Uu7xy6qNwdIDQAA 4 @@ -953,7 +950,7 @@ eu5J5ZGSGUmZFfbh0cHFewAA AeNNCbWnPEKWIb774GWlfQAA - + NmvwO09X4Uu7xy6qNwdIDQAA JQvuxGbsdE2jFadShkxqKgAA g0zWWZA9xEWvFh0sRnmMqgAA @@ -963,7 +960,7 @@ oxtgEPTKIkyuZW+/1ioAPAAA C3LeagDb40ac4fqEDvNK5AAA - + NmvwO09X4Uu7xy6qNwdIDQAA rDKOyCdZEkCOx+oFSF1RfgAA lPra4OiszU2H/arMBBwTVgAA @@ -973,7 +970,7 @@ cxdf5fynWEG7/Wzlz9wAZgAA COnrVcktJUCdGcPafp3OSAAA - + NmvwO09X4Uu7xy6qNwdIDQAA 4 qO84lDa9Q0qJdFLxAzRcQQAA @@ -986,8 +983,8 @@ g0zWWZA9xEWvFh0sRnmMqgAA 4 6HcxdQob+UOT1wCYJ4QeHgAA -MfI12JH1kkSbXGyVvMqqXQAA -tMamOzqFxk6hZeNgqluobwAA +tMamOzqFxk6hZeNgqluobwAA +MfI12JH1kkSbXGyVvMqqXQAA /ARNc/hPvUmBl4qb/XiPqQAA @@ -996,12 +993,12 @@ q11CD3et4kixnDRLW4nPdgAA 4 ymxDIXyVUESDyLIcICrGWQAA -9JS131H/4US3bVVB0X+RIAAA -I8zAzIUs30G8GAyGAkzPOAAA +I8zAzIUs30G8GAyGAkzPOAAA +9JS131H/4US3bVVB0X+RIAAA itBAlqtdlUK0IXNYnX3+mQAA - + creates NmvwO09X4Uu7xy6qNwdIDQAA 4 @@ -1016,8 +1013,8 @@ rDKOyCdZEkCOx+oFSF1RfgAA 4 hIeXX5pEhk+9J80xff/Z2QAA -Jn/ACJad8kOY5lGCpXLetQAA -USMA9tEXpkGY+pAIVRjLHAAA +USMA9tEXpkGY+pAIVRjLHAAA +Jn/ACJad8kOY5lGCpXLetQAA WNomTSYdhk6j1wGMK0aBMQAA @@ -1025,24 +1022,24 @@ JQvuxGbsdE2jFadShkxqKgAA 4 vMwGVXrxPkCKOvOAPR6ytQAA -BAaRrPSiRkWfQQrnfeF5BQAA -b6bOArvlz0+mgsrQHIOI8wAA +b6bOArvlz0+mgsrQHIOI8wAA +BAaRrPSiRkWfQQrnfeF5BQAA rACoLZEoXESlgVdLXl1ocQAA - + SomePlugin NmvwO09X4Uu7xy6qNwdIDQAA 1 xW95yby7XEChYzUI8UtliAAA - + ConE NmvwO09X4Uu7xy6qNwdIDQAA 1 Nppn0CUEP0Stsi3DAR1qEQAA - + uses NmvwO09X4Uu7xy6qNwdIDQAA 4 @@ -1057,8 +1054,8 @@ q11CD3et4kixnDRLW4nPdgAA 4 YQ4SH0PbkU6D2Ed6kFWZ3gAA -au7s+O1a6EOhU92BZ9mTfAAA -uC7b5/Ag8E+lVXijU0puEAAA +uC7b5/Ag8E+lVXijU0puEAAA +au7s+O1a6EOhU92BZ9mTfAAA SutSAX/p70WlhiBCYP5mIQAA @@ -1066,12 +1063,12 @@ 3dlH2vm6sEayyvEaXZoCngAA 4 Rn+WUty/KE6o3UWIZm/++wAA -7gOWzEGpb0KSajbXDeX03QAA -e/X32+GrOUiRRJMneGhhrwAA +e/X32+GrOUiRRJMneGhhrwAA +7gOWzEGpb0KSajbXDeX03QAA 1RN9/oe60kCHXG3xE2fYmQAA - + uses NmvwO09X4Uu7xy6qNwdIDQAA 4 @@ -1086,8 +1083,8 @@ 3dlH2vm6sEayyvEaXZoCngAA 4 Ao1mzGyZkUOXJ7iUZ+CxmQAA -Mlo0JoqcnUWmKG46gdW/pgAA -60bFmV8mJ02N5+zPFmP+cAAA +60bFmV8mJ02N5+zPFmP+cAAA +Mlo0JoqcnUWmKG46gdW/pgAA hQN6K9SliEunBHaWLwTWywAA @@ -1095,8 +1092,8 @@ rDKOyCdZEkCOx+oFSF1RfgAA 4 65oSMAg0mkmODMiMbf+UjQAA -6vvMJYaqA0+EsdkZT8o6oAAA -znikN5jxMkWgoTVeUx7U0wAA +znikN5jxMkWgoTVeUx7U0wAA +6vvMJYaqA0+EsdkZT8o6oAAA AnbfKLYaZ0qC8tWUwfnFkgAA 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 ```` element. +Here the *model* consists just of the class Output, which corresponds to the ```` element. + +In addition to these, there is a collection of *validator classes* that are +responsible for handling model-level validation. Plug-in code ------------ @@ -135,6 +143,28 @@ .. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_reader.py :linenos: +Note that the reader class provides the XML schema by overriding +``get_schema_data()``. If this method was not overridden, a default schema +that accepts (almost) anything would be used for schema validation. + + +exampleml_validators.py +................... + +This file defines all validator classes. Since ExampleML is so simple, there +are only two cases that need to be validated on the model level: setting +references and the encoding. Notice that the setting reference validator +uses the method ``check_feature_reference()`` inherited from ``ImplValidatorBase``. +As there are utility functions for handling references in a uniform way, there +is also a utility function for validating them. + +Note also the class list VALIDATOR_CLASSES at the bottom, which contains both +of the validator classes. The file ``setup.py`` contains an entry point +definition that points to this list, and the validation framework finds the +validators via that. + +.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_validators.py + :linenos: Unit tests ---------- @@ -204,14 +234,26 @@ .. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_generation.py :linenos: +unittest_exampleml_validation.py +................................ + +Like ``unittest_exampleml_generation.py`` test output generation, this file +tests validation. The test cases themselves are pretty simple, since there are +pre-existing helper methods for running the tests, and the tests mainly consist +of test data and expected. + +.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_validation.py + :linenos: + + Plug-in packaging ----------------- The file ``setup.py`` handles the packaging of the plug-in into an egg file. The most important thing here is the plug-in's entry point info. The -plug-in's reader classes must be specified as entry points, or they won't be -loaded. +plug-in's reader and validator classes must be specified as entry points, +or they won't be loaded. .. literalinclude:: /../source/plugins/example/ConeExamplePlugin/setup.py :linenos: @@ -268,11 +310,11 @@ This file contains tests for generating output using the example plug-in. Note the following things: -- The use of the variable ``CONE_CMD`` in ``get_cmd()``. This variable is set to - contain the actual ConE command to run if the tests are being run from the - exported standalone test set. In practice this will be something like - ``C:/cone_test/cone/cone.cmd``. -- The actual generation and testing is done in a separate function, ``run_test_generate()``, +- The check if ``CONE_CMD`` is in the environment variables in ``get_cmd()``. + This variable is set to contain the actual ConE command to run if the tests + are being run from the exported standalone test set. In practice this will be + something like ``C:/cone_test/cone/cone.cmd``. +- The actual generation and testing is done in a separate function, ``_run_test_generate()``, and there are two actual test functions that call it. One runs the test directly on the test project on the file system, and another first zips the test project and then runs the test on that. It is a good idea to test that generation works the same in both cases, diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/impl-validation-classes.jpg Binary file configurationengine/doc/plugins/dev-plugin/impl-validation-classes.jpg has changed diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/index.rst --- a/configurationengine/doc/plugins/dev-plugin/index.rst Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/doc/plugins/dev-plugin/index.rst Tue Aug 10 14:29:28 2010 +0300 @@ -1,19 +1,18 @@ .. _plugin-howto: -How to create a ConE plug-in -============================ +How to create an implementation plug-in for ConE +================================================ -This page contains a description of ConE's plug-in interface, a description of +This page contains a description of an example plug-in intended to be used as a template for creating new plug-ins, -and step-by-step instructions for creating a new ConE plug-in based on the template. +and step-by-step instructions for creating a new ConE implementation plug-in based on the template. The impatient can simply skip to the step-by-step instructions, by it is recommended -to read the also the plug-in interface and example plug-in descriptions. +to read the also the :ref:`plug-in interface ` and example plug-in descriptions. The instructions assume that the used development environment is Eclipse/PyDev. .. toctree:: :maxdepth: 3 - plugin-interface example-plugin steps diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/model-validation.uml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/dev-plugin/model-validation.uml Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,2760 @@ + + + + + + + + + + +Untitled +3 + +Model1 +UgzTZtXBekmk2L7FzuhqeQAA +2 + +ImplmlValidation +J0JbQTHSq0yi13n61FmjzgAA + +BizY3ycO40CY71lR17niowAA +30 + +clMaroon +$00B9FFFF +432 +508 +153 +125 +omsxqqbK/UWCHBKe5JrDagAA + + +cone.public.plugin + + +False + + +False + + + + +clMaroon +$00B9FFFF +208 +104 +397 +301 +2qWKZicOf06yzOTeZuyqCAAA + + +cone.validation.implmlvalidation + + +False + + +False + + + + +clMaroon +$00B9FFFF +424 +297 +155 +69 +XjBwLw9OjEmKJ4KD8B58wgAA + + +3 +ImplValidatorBase + + +False + + +False + + + +XjBwLw9OjEmKJ4KD8B58wgAA + + +XjBwLw9OjEmKJ4KD8B58wgAA + + +False +XjBwLw9OjEmKJ4KD8B58wgAA + + + +clMaroon +$00B9FFFF +664 +288 +221 +157 +SI/VACVeYUOmYmmg2TSKaQAA + + +crmlplugin.crml_validators + + +False + + +False + + + + +clMaroon +$00B9FFFF +676 +332 +145 +43 +wbvMqm+/yE2hNe1Utj7f9AAA + + +1 +CrmlReferenceValidator + + +False + + +False + + + +wbvMqm+/yE2hNe1Utj7f9AAA + + +wbvMqm+/yE2hNe1Utj7f9AAA + + +False +wbvMqm+/yE2hNe1Utj7f9AAA + + + +clMaroon +$00B9FFFF +676 +384 +158 +43 +Cy+SmuqmpkSX9nQNWXF+MgAA + + +1 +CrmlDuplicateUidValidator + + +False + + +False + + + +Cy+SmuqmpkSX9nQNWXF+MgAA + + +Cy+SmuqmpkSX9nQNWXF+MgAA + + +False +Cy+SmuqmpkSX9nQNWXF+MgAA + + + +clMaroon +$00B9FFFF +682,384;578,354 +Kc/JhhXZ9kaQvIqg52hkzQAA +3goKGKxfG0uL8r408fsXYQAA +POGF8jlAQ0WHmmVN5I344AAA + +False +1.5707963267949 +15 +Kc/JhhXZ9kaQvIqg52hkzQAA + + +False +1.5707963267949 +30 +Kc/JhhXZ9kaQvIqg52hkzQAA + + +False +-1.5707963267949 +15 +Kc/JhhXZ9kaQvIqg52hkzQAA + + + +clMaroon +$00B9FFFF +676,347;578,338 +6sSq0GCuIUuD+jUJQcViugAA +3goKGKxfG0uL8r408fsXYQAA +UjOB3AO2S0SO11NmkC+uFwAA + +False +1.5707963267949 +15 +6sSq0GCuIUuD+jUJQcViugAA + + +False +1.5707963267949 +30 +6sSq0GCuIUuD+jUJQcViugAA + + +False +-1.5707963267949 +15 +6sSq0GCuIUuD+jUJQcViugAA + + + +clMaroon +$00B9FFFF +228 +296 +111 +73 +nx3Lx4aZoUSFCSv3hH2xRgAA + + +1 +ValidationContext + + +False + + +False + + + +nx3Lx4aZoUSFCSv3hH2xRgAA + + +nx3Lx4aZoUSFCSv3hH2xRgAA + + +False +nx3Lx4aZoUSFCSv3hH2xRgAA + + + +clMaroon +$00B9FFFF +lsRectilinear +338,332;424,332 +9tUo6t0cgkqrFSmHsMYuAAAA +3goKGKxfG0uL8r408fsXYQAA +g14za6T92EGNk4PWs/vUjQAA + +False +1.5707963267949 +15 +9tUo6t0cgkqrFSmHsMYuAAAA + + +False +1.5707963267949 +30 +9tUo6t0cgkqrFSmHsMYuAAAA + + +False +-1.5707963267949 +15 +9tUo6t0cgkqrFSmHsMYuAAAA + + +-0.523598775598299 +30 +epHead ++context +to4Ge8pEOk6oiY69/D4VDgAA + + +False +0.523598775598299 +30 +epTail ++FD +q6CV7L6RD0ipPZFD0c2e1wAA + + +False +0.523598775598299 +25 +epHead +to4Ge8pEOk6oiY69/D4VDgAA + + +False +-0.523598775598299 +25 +epTail +q6CV7L6RD0ipPZFD0c2e1wAA + + +False +-0.785398163397448 +40 +epHead +to4Ge8pEOk6oiY69/D4VDgAA + + +False +0.785398163397448 +40 +epTail +q6CV7L6RD0ipPZFD0c2e1wAA + + +False +-888 +-828 +50 +8 +to4Ge8pEOk6oiY69/D4VDgAA + + +False +-888 +-828 +50 +8 +q6CV7L6RD0ipPZFD0c2e1wAA + + + +clMaroon +$00B9FFFF +456 +556 +91 +43 +cQYhYY9L50KRVH8GX320RAAA + + +3 +ImplBase + + +False + + +False + + + +cQYhYY9L50KRVH8GX320RAAA + + +cQYhYY9L50KRVH8GX320RAAA + + +False +cQYhYY9L50KRVH8GX320RAAA + + + +clMaroon +$00B9FFFF +788 +456 +178 +38 +Plug-ins provide validator classes +via an egg entry point. + + + +clMaroon +$00B9FFFF +791,426;844,456 +AWb6hJZcbU+VJwaQPrrTdgAA +POGF8jlAQ0WHmmVN5I344AAA + + +clMaroon +$00B9FFFF +501,556;501,365 +lMyxDaFSF0SCrMvdMMibSwAA +3goKGKxfG0uL8r408fsXYQAA +c5pkkfn3Xk2arAYxl83oLgAA + +False +1.5707963267949 +15 +lMyxDaFSF0SCrMvdMMibSwAA + + +False +1.5707963267949 +30 +lMyxDaFSF0SCrMvdMMibSwAA + + +False +-1.5707963267949 +15 +lMyxDaFSF0SCrMvdMMibSwAA + + +-0.523598775598299 +30 +epHead ++impl +GfSW7NI3NEORsulHu2l+XgAA + + +False +0.523598775598299 +30 +epTail +xO0O32Ik5UKs7FALsy3uPQAA + + +False +0.523598775598299 +25 +epHead +GfSW7NI3NEORsulHu2l+XgAA + + +False +-0.523598775598299 +25 +epTail +xO0O32Ik5UKs7FALsy3uPQAA + + +False +-0.785398163397448 +40 +epHead +GfSW7NI3NEORsulHu2l+XgAA + + +False +0.785398163397448 +40 +epTail +xO0O32Ik5UKs7FALsy3uPQAA + + +False +-888 +-820 +50 +8 +GfSW7NI3NEORsulHu2l+XgAA + + +False +-888 +-820 +50 +8 +xO0O32Ik5UKs7FALsy3uPQAA + + + +clMaroon +$00B9FFFF +604 +508 +214 +143 +Each validator class lists the +implementation classes it supports. + +When validating an implementation, +the framework checks for each +registered validator class if it supports +the current implementation. If so, +a validator instance is created and +it is used to validate the implementation. + + + +clMaroon +$00B9FFFF +530,365;650,508 +oHULdTV6v0uuFqaiVKIWYgAA +3goKGKxfG0uL8r408fsXYQAA + + +clMaroon +$00B9FFFF +546,577;604,578 +oHULdTV6v0uuFqaiVKIWYgAA +c5pkkfn3Xk2arAYxl83oLgAA + + +clMaroon +$00B9FFFF +436 +176 +123 +43 +w1x85nyRiUi3HLBob1jwlQAA + + +3 +GlobalValidatorBase + + +False + + +False + + + +w1x85nyRiUi3HLBob1jwlQAA + + +w1x85nyRiUi3HLBob1jwlQAA + + +False +w1x85nyRiUi3HLBob1jwlQAA + + + +clMaroon +$00B9FFFF +264 +168 +100 +69 +WfkxoUbZqUOof1sQP1YufAAA + + +3 +ValidatorBase + + +False + + +False + + + +WfkxoUbZqUOof1sQP1YufAAA + + +WfkxoUbZqUOof1sQP1YufAAA + + +False +WfkxoUbZqUOof1sQP1YufAAA + + + +clMaroon +$00B9FFFF +451,297;363,236 +TFV/zVsrMESTDkTEnyr/rAAA +y/GCWOvnj0elYh+OdbeO9gAA +3goKGKxfG0uL8r408fsXYQAA + +False +1.5707963267949 +15 +TFV/zVsrMESTDkTEnyr/rAAA + + +False +1.5707963267949 +30 +TFV/zVsrMESTDkTEnyr/rAAA + + +False +-1.5707963267949 +15 +TFV/zVsrMESTDkTEnyr/rAAA + + + +clMaroon +$00B9FFFF +lsRectilinear +436,198;363,198 +sh0Wc2GWw02v4RJbRczpBwAA +y/GCWOvnj0elYh+OdbeO9gAA +TEw9LFZNuE+vJNGP9lmkkQAA + +False +1.5707963267949 +15 +sh0Wc2GWw02v4RJbRczpBwAA + + +False +1.5707963267949 +30 +sh0Wc2GWw02v4RJbRczpBwAA + + +False +-1.5707963267949 +15 +sh0Wc2GWw02v4RJbRczpBwAA + + + +clMaroon +$00B9FFFF +24 +48 +211 +173 +ImplML validation happens using +validator classes. Each validator +checks for only one specific sort of +problem (or at most a few). + +PROBLEM_TYPES specifies the types of +problems the validator class produces, +so the validator classes can be filtered +using the problem filter, and the +validation code for those does not need +to be run unnecessarily. + + + +clMaroon +$00B9FFFF +264,184;234,173 +sUc4obK/ZEa9nz+c1miVhwAA +y/GCWOvnj0elYh+OdbeO9gAA + + +clMaroon +$00B9FFFF +364 +32 +231 +53 +Validators deriving from GlobalValidatorBase +validate the whole implementation set +at once. These are pretty rare cases. + + + +clMaroon +$00B9FFFF +494,176;482,84 +Jnc/ZHbN/U2fSg2Fi1cCCAAA +TEw9LFZNuE+vJNGP9lmkkQAA + + +clMaroon +$00B9FFFF +672 +104 +233 +105 +Md0YIXCoWEGWJR7Ev5Wv5AAA + + +cone.validation.builtinvalidators.implml + + +False + + +False + + + + +clMaroon +$00B9FFFF +688 +148 +209 +43 +dtL6oUxsS0aPIWsKeupmrwAA + + +1 +DuplicateTempFeatureRefValidator + + +False + + +False + + + +dtL6oUxsS0aPIWsKeupmrwAA + + +dtL6oUxsS0aPIWsKeupmrwAA + + +False +dtL6oUxsS0aPIWsKeupmrwAA + + + +clMaroon +$00B9FFFF +688,179;558,191 +SYK6JJaoy0SMuQ+WSY9s/QAA +TEw9LFZNuE+vJNGP9lmkkQAA +1HH9DFhjeUaISb6w7/0iHwAA + +False +1.5707963267949 +15 +SYK6JJaoy0SMuQ+WSY9s/QAA + + +False +1.5707963267949 +30 +SYK6JJaoy0SMuQ+WSY9s/QAA + + +False +-1.5707963267949 +15 +SYK6JJaoy0SMuQ+WSY9s/QAA + + + +clMaroon +$00B9FFFF +636 +8 +178 +83 +Mainly ImplML validators come +from plug-ins, but there is also +a set of built-in validator classes +(for validating ImplContainer +instances). + + + +clMaroon +$00B9FFFF +757,104;749,90 +SuIMeQW7gk6KodeUMOeXnwAA +oyJAaWjr+06Ztadvt0qcowAA + + + + +ConfmlValidation +J0JbQTHSq0yi13n61FmjzgAA + +iijTyCe1nke1ngA2DWMMDAAA +19 + +clMaroon +$00B9FFFF +548 +120 +215 +157 +gb1B3r/wIkeUDgFfr7dtwwAA + + +cone.validation.builtinvalidator.confml + + +False + + +False + + + + +clMaroon +$00B9FFFF +88 +96 +373 +185 +Wl0JQVQ3CEuxp+MiuIDDVQAA + + +cone.validation.confmlvalidation + + +False + + +False + + + + +clMaroon +$00B9FFFF +112 +140 +111 +95 +6WAPzjt1AUKuMkcJEQnMNAAA + + +1 +ValidationContext + + +False + + +False + + + +6WAPzjt1AUKuMkcJEQnMNAAA + + +6WAPzjt1AUKuMkcJEQnMNAAA + + +False +6WAPzjt1AUKuMkcJEQnMNAAA + + + +clMaroon +$00B9FFFF +304 +156 +100 +69 +yeAzLzipb0S50RpYIsQH2gAA + + +3 +ValidatorBase + + +False + + +False + + + +yeAzLzipb0S50RpYIsQH2gAA + + +yeAzLzipb0S50RpYIsQH2gAA + + +False +yeAzLzipb0S50RpYIsQH2gAA + + + +clMaroon +$00B9FFFF +222,188;304,189 +a+P0rhTH2kieoO26fePJcAAA +ogVxPBQL3k6pyOzvc0MMFAAA +5sQAX2rJOESpxsazqtjv/wAA + +False +1.5707963267949 +15 +a+P0rhTH2kieoO26fePJcAAA + + +False +1.5707963267949 +30 +a+P0rhTH2kieoO26fePJcAAA + + +False +-1.5707963267949 +15 +a+P0rhTH2kieoO26fePJcAAA + + +-0.523598775598299 +30 +epHead ++context +2zKLgXw7zUKcrd3FmFVP3wAA + + +False +0.523598775598299 +30 +epTail +BmDMhTlKJkKpLaJwiCOBZwAA + + +False +0.523598775598299 +25 +epHead +2zKLgXw7zUKcrd3FmFVP3wAA + + +False +-0.523598775598299 +25 +epTail +BmDMhTlKJkKpLaJwiCOBZwAA + + +False +-0.785398163397448 +40 +epHead +2zKLgXw7zUKcrd3FmFVP3wAA + + +False +0.785398163397448 +40 +epTail +BmDMhTlKJkKpLaJwiCOBZwAA + + +False +-1080 +-984 +50 +8 +2zKLgXw7zUKcrd3FmFVP3wAA + + +False +-1080 +-984 +50 +8 +BmDMhTlKJkKpLaJwiCOBZwAA + + + +clMaroon +$00B9FFFF +588 +164 +124 +43 +hborxSDNsk2fbR0/hWRHNgAA + + +1 +MaxLengthValidator + + +False + + +False + + + +hborxSDNsk2fbR0/hWRHNgAA + + +hborxSDNsk2fbR0/hWRHNgAA + + +False +hborxSDNsk2fbR0/hWRHNgAA + + + +clMaroon +$00B9FFFF +588,186;403,189 +x3PVKMHyJUO0m0hk6x6+8QAA +ogVxPBQL3k6pyOzvc0MMFAAA +qOPIH+pKDEWBtOJbZYgCaAAA + +False +1.5707963267949 +15 +x3PVKMHyJUO0m0hk6x6+8QAA + + +False +1.5707963267949 +30 +x3PVKMHyJUO0m0hk6x6+8QAA + + +False +-1.5707963267949 +15 +x3PVKMHyJUO0m0hk6x6+8QAA + + + +clMaroon +$00B9FFFF +588 +216 +120 +43 +S5CFGHNdFU+TPZnIr60XEAAA + + +1 +MinLengthValidator + + +False + + +False + + + +S5CFGHNdFU+TPZnIr60XEAAA + + +S5CFGHNdFU+TPZnIr60XEAAA + + +False +S5CFGHNdFU+TPZnIr60XEAAA + + + +clMaroon +$00B9FFFF +588,228;403,198 +SVsn2qUKTEmmF2QmMwcJnAAA +ogVxPBQL3k6pyOzvc0MMFAAA +z9HhgfsZpk6vQG5aOdZBKQAA + +False +1.5707963267949 +15 +SVsn2qUKTEmmF2QmMwcJnAAA + + +False +1.5707963267949 +30 +SVsn2qUKTEmmF2QmMwcJnAAA + + +False +-1.5707963267949 +15 +SVsn2qUKTEmmF2QmMwcJnAAA + + + +clMaroon +$00B9FFFF +380 +372 +133 +117 +LaydkygZykqnLCXC9YglFgAA + + +fooplugin.foovalidators + + +False + + +False + + + + +clMaroon +$00B9FFFF +400 +424 +90 +43 +W4OOCM1jAEK5Dgre8fmqTAAA + + +1 +FooValidator + + +False + + +False + + + +W4OOCM1jAEK5Dgre8fmqTAAA + + +W4OOCM1jAEK5Dgre8fmqTAAA + + +False +W4OOCM1jAEK5Dgre8fmqTAAA + + + +clMaroon +$00B9FFFF +437,424;365,224 +NwUHVYoqBUydydMZ2tDe4QAA +ogVxPBQL3k6pyOzvc0MMFAAA +RMmkBo4Wy0uDlgbbF8qp9AAA + +False +1.5707963267949 +15 +NwUHVYoqBUydydMZ2tDe4QAA + + +False +1.5707963267949 +30 +NwUHVYoqBUydydMZ2tDe4QAA + + +False +-1.5707963267949 +15 +NwUHVYoqBUydydMZ2tDe4QAA + + + +clMaroon +$00B9FFFF +516 +324 +204 +68 +The confmlvalidation module contains +the built-in validators, but plug-ins can +also provide custom validators via an +egg entry point. + + + +clMaroon +$00B9FFFF +636,276;625,324 +H7s5kCj7L0aVT3PqpTfoWwAA +sm9uFVeIzEybVzNh0ZD+ywAA + + +clMaroon +$00B9FFFF +512,402;538,391 +H7s5kCj7L0aVT3PqpTfoWwAA +qfGVeEllc0uRJYtt+gcmLQAA + + +clMaroon +$00B9FFFF +440 +12 +161 +68 +Like with ImplML validation, +a validator is responsible only +for generating problems of a +specific type. + + + +clMaroon +$00B9FFFF +392,156;481,79 +X6ZcBnf5GUGlnTTo1b8fKAAA +ogVxPBQL3k6pyOzvc0MMFAAA + + +clMaroon +$00B9FFFF +68 +336 +244 +83 +The context contains the input (configuration) +and the output (problems), but also all sorts of +other data, e.g. a list of all features, so that +validators do not need to build it themselves +by traversing the model. + + + +clMaroon +$00B9FFFF +172,234;184,336 +wYBm24foAkuCyXNp5c7rPwAA +5sQAX2rJOESpxsazqtjv/wAA + + + +18 + +cone.validation.implmlvalidation +J0JbQTHSq0yi13n61FmjzgAA +1 +cBNU63cyHkyOttvWiFCzXAAA +4 + +ImplValidatorBase +True +2qWKZicOf06yzOTeZuyqCAAA +4 +3goKGKxfG0uL8r408fsXYQAA +1QldCtJUsECyFTsbu3s9XgAA +GwJF7Uc2qkucIa/W7XCSFwAA +Vg23dTmL40WKOmiqnNYWwQAA +2 +Kc/JhhXZ9kaQvIqg52hkzQAA +6sSq0GCuIUuD+jUJQcViugAA +1 +TFV/zVsrMESTDkTEnyr/rAAA +1 + +validate +True +XjBwLw9OjEmKJ4KD8B58wgAA + +2 +to4Ge8pEOk6oiY69/D4VDgAA +GfSW7NI3NEORsulHu2l+XgAA +1 + +SUPPORTED_IMPL_CLASSES +skClassifier +skClassifier +XjBwLw9OjEmKJ4KD8B58wgAA + + + +ValidationContext +2qWKZicOf06yzOTeZuyqCAAA +4 +g14za6T92EGNk4PWs/vUjQAA +yEtGoC/OVU+MtM58Kcp8eQAA +sl4ETPFlpUmkpdJ3lTHfCAAA +aSfLN5cFNkW4AgKNImQMDAAA +1 +q6CV7L6RD0ipPZFD0c2e1wAA +2 + +configuration +nx3Lx4aZoUSFCSv3hH2xRgAA + + +problems +nx3Lx4aZoUSFCSv3hH2xRgAA + + + +ValidatorBase +True +2qWKZicOf06yzOTeZuyqCAAA +4 +y/GCWOvnj0elYh+OdbeO9gAA +/gHyKKAz8E2mAa0etgNEMQAA +9uZgXfUGFUWwEn2HwyGyLAAA +4sk3WJs3VUakc5yh9IJfcAAA +2 +TFV/zVsrMESTDkTEnyr/rAAA +sh0Wc2GWw02v4RJbRczpBwAA +1 + +validate +WfkxoUbZqUOof1sQP1YufAAA + +1 + +PROBLEM_TYPES +skClassifier +WfkxoUbZqUOof1sQP1YufAAA + + + +GlobalValidatorBase +True +2qWKZicOf06yzOTeZuyqCAAA +4 +TEw9LFZNuE+vJNGP9lmkkQAA +CJx7Itfy7Uibwjeyw5yQDQAA +jFGd4I3bN0K55FxynMIRQwAA +z0uyUnKnI0Gaw2xWrA8UsgAA +1 +SYK6JJaoy0SMuQ+WSY9s/QAA +1 +sh0Wc2GWw02v4RJbRczpBwAA + + + +crmlplugin.crml_validators +J0JbQTHSq0yi13n61FmjzgAA +1 +9RQji6pg1U2ipqsxknfe8gAA +2 + +CrmlReferenceValidator +SI/VACVeYUOmYmmg2TSKaQAA +4 +UjOB3AO2S0SO11NmkC+uFwAA +VsZ1ugd2fUCdG5xIOrwxdwAA +j2iWaOgMlEKIj8vhMaHFfQAA +wtdyekaYd0KBv6UhMLDnewAA +1 +6sSq0GCuIUuD+jUJQcViugAA + + +CrmlDuplicateUidValidator +SI/VACVeYUOmYmmg2TSKaQAA +4 +POGF8jlAQ0WHmmVN5I344AAA +WCx5ai4Z1kijSbAQp7n+6AAA +VtgEwJKxc0aWpNn81zMWxgAA +HM/6PUALRU+eMxw64yLK/QAA +1 +Kc/JhhXZ9kaQvIqg52hkzQAA + + + +J0JbQTHSq0yi13n61FmjzgAA +Cy+SmuqmpkSX9nQNWXF+MgAA +XjBwLw9OjEmKJ4KD8B58wgAA +4 +oqIw0IFa9kWea9XTuFMZ1AAA +4Ju7YjWI0kS3NUyxQah2ZQAA +NHJXrkZ9iUao9zyQg2EKugAA +mIgLnOfmNkCkHAhbqSNpDgAA + + +J0JbQTHSq0yi13n61FmjzgAA +wbvMqm+/yE2hNe1Utj7f9AAA +XjBwLw9OjEmKJ4KD8B58wgAA +4 +ysaiWR11jkCPXTaPKqvETAAA +15dM8+2xdUqVA0PEz4Z+lAAA +Yy5JZoVrZk6fO/HBzcXbLQAA +rdBsD6yDGUCxMqzu4s/5jgAA + + +J0JbQTHSq0yi13n61FmjzgAA +4 +G4BGfDCjwkO+jlXwGuVFJwAA +4KvH0CBxeE6GrVd/KPRCVAAA +Q/jeLaNxY0mQNbmb5EjLqwAA +2wPc15TFakOVGaYagKeKWQAA +2 + +9tUo6t0cgkqrFSmHsMYuAAAA +nx3Lx4aZoUSFCSv3hH2xRgAA +4 +MetUdT1H9UuvGWMD17NpFQAA +slOChvPyFUqAdCyKfHjcvAAA +yPzKg0VG3kSo7bwqixJw5wAA +yIiEf+5aYkWbTpXOnT53ggAA + + +context +akAggregate +9tUo6t0cgkqrFSmHsMYuAAAA +XjBwLw9OjEmKJ4KD8B58wgAA +4 +VheCL5brfEmRNkId9sisYAAA +9iTNYzJ5TUuDLk/vA1PFmwAA +QuuWBk9xWkmhDNnTN1VaFgAA +42cJ86Z/+0K6N/F17BRRBQAA + + + +J0JbQTHSq0yi13n61FmjzgAA +4 +chIlFeu+W0CfzByUAT+hMAAA +wuLJ37KQ8EuRL4PCZItYNwAA +D5NQL72A30SlV3uTGM6S/wAA +rF4ks9l5TkGOHIUJ8vyKmwAA +2 + +lMyxDaFSF0SCrMvdMMibSwAA +cQYhYY9L50KRVH8GX320RAAA +4 +xEctc7E62kSVYwICvYhLmwAA +t5ygmZQvmketK0B1UlCGyAAA +usGQ87TWBUu3+WGQUcXqYQAA +Xt49OQdNiEOsCMaWsliTKgAA + + +impl +akAggregate +lMyxDaFSF0SCrMvdMMibSwAA +XjBwLw9OjEmKJ4KD8B58wgAA +4 +gNKP+7f4V02nCGw0oisRogAA +fvH9lFDYXUOQ4sZb1bq8JwAA +n0abP8A4Kky9OwOpQrrd/AAA +vxzp55tliEacRjs1Bzk+KQAA + + + +cone.public.plugin +J0JbQTHSq0yi13n61FmjzgAA +1 +EJCUtlLZ2EmiEUOBxXASmAAA +1 + +ImplBase +True +omsxqqbK/UWCHBKe5JrDagAA +4 +c5pkkfn3Xk2arAYxl83oLgAA +Ylq6cKNmOE+S+jAz03hfeAAA +rOLzdil6uECps+oXj/rh5QAA +2bQ9ix8R0kGXUdsUVLOfmwAA +1 +xO0O32Ik5UKs7FALsy3uPQAA + + + +cone.validation.confmlvalidation +J0JbQTHSq0yi13n61FmjzgAA +1 +P3ezBGNoxUSwo3wuAMVFiAAA +2 + +ValidationContext +Wl0JQVQ3CEuxp+MiuIDDVQAA +4 +5sQAX2rJOESpxsazqtjv/wAA +hDcwGnPSZEimcb15NFHnOAAA +IM1WlpZrKEqwEHUaM74EFAAA +EI3ZLQJ4ak2I2jQ+4aOQ4wAA +1 +BmDMhTlKJkKpLaJwiCOBZwAA +3 + +configuration +6WAPzjt1AUKuMkcJEQnMNAAA + + +feature_dict +6WAPzjt1AUKuMkcJEQnMNAAA + + +problems +6WAPzjt1AUKuMkcJEQnMNAAA + + + +ValidatorBase +True +Wl0JQVQ3CEuxp+MiuIDDVQAA +4 +ogVxPBQL3k6pyOzvc0MMFAAA +xj1GtlFznUasqLxmUZeJcwAA +Leqp3IYyvEKQTTTtNSjC7wAA +GnFhUdzPmEa3rwo8LcYKEQAA +3 +x3PVKMHyJUO0m0hk6x6+8QAA +SVsn2qUKTEmmF2QmMwcJnAAA +NwUHVYoqBUydydMZ2tDe4QAA +1 + +validate +True +yeAzLzipb0S50RpYIsQH2gAA + +1 +2zKLgXw7zUKcrd3FmFVP3wAA +1 + +PROBLEM_TYPES +skClassifier +skClassifier +yeAzLzipb0S50RpYIsQH2gAA + + + + +J0JbQTHSq0yi13n61FmjzgAA +4 +OO3OuToGd0unmYJL9p4BcgAA +Jf3WcoK5rkK0bXKIzzP1LwAA +E5yN6PLtpkiSBcAATCm/CgAA +dEV2q1LebUmoTMPYClzbqwAA +2 + +a+P0rhTH2kieoO26fePJcAAA +6WAPzjt1AUKuMkcJEQnMNAAA +4 +LXveBLUSk024mZkKltY4VQAA +jFZFyZ5BKEGQ2J0Zo9QgvQAA +K5g2QnUcyUGngPoEWoXatwAA +EFO+Bga4PUWWBm9ayJ5PFAAA + + +context +akAggregate +a+P0rhTH2kieoO26fePJcAAA +yeAzLzipb0S50RpYIsQH2gAA +4 +vbnMU/dM+0O0vafILK/dSwAA +zdAyL2g1+0WkJ4IeOTOggQAA +ncLwP0F7NUCXrZIiSdoUHgAA +KGEeUhgfWUCyUQxhCDRf3gAA + + + +J0JbQTHSq0yi13n61FmjzgAA +hborxSDNsk2fbR0/hWRHNgAA +yeAzLzipb0S50RpYIsQH2gAA +4 +qV4ITWMWLU6VMUw0NGujcQAA +bzqSN6R+nUuCmmCmE3g3UAAA +LoJmdkzjLE6NtolTzPHITAAA +wO7Dtbem4k2F4ew1uxznzAAA + + +J0JbQTHSq0yi13n61FmjzgAA +S5CFGHNdFU+TPZnIr60XEAAA +yeAzLzipb0S50RpYIsQH2gAA +4 +3SoG4OJ000uW8mQ1rd9WfAAA +fdSow+ETWEizVTlugKms7wAA +PgumoRJ2pU67+WAiaOS0lwAA +4p1y9ojoTkOUrWgaa6wB7QAA + + +fooplugin.foovalidators +J0JbQTHSq0yi13n61FmjzgAA +1 +qfGVeEllc0uRJYtt+gcmLQAA +1 + +FooValidator +LaydkygZykqnLCXC9YglFgAA +4 +RMmkBo4Wy0uDlgbbF8qp9AAA +WMsOpu0SNky1x3JnGxUpCQAA +Jn5ocjLA20e+fh9gbFcRMQAA +u/dPvwRLi0iaQ3TkhlpThAAA +1 +NwUHVYoqBUydydMZ2tDe4QAA + + + +J0JbQTHSq0yi13n61FmjzgAA +W4OOCM1jAEK5Dgre8fmqTAAA +yeAzLzipb0S50RpYIsQH2gAA +4 +vTs2mU66JUuBuD3YYBowNgAA +9LpNxmfD5UaMQzxQUSzZoQAA +Q18hr5MPjE+KKV+74W27RAAA +JvIT766O7ECZQysR8GwXAQAA + + +cone.validation.builtinvalidator.confml +J0JbQTHSq0yi13n61FmjzgAA +1 +sm9uFVeIzEybVzNh0ZD+ywAA +2 + +MaxLengthValidator +gb1B3r/wIkeUDgFfr7dtwwAA +4 +qOPIH+pKDEWBtOJbZYgCaAAA +5U3ADC9fokmZPYm91Xd3mAAA +M4a94cLxpkGVKOxShuVFqQAA +NeV2eYQyR0aQwtSl4rhQhQAA +1 +x3PVKMHyJUO0m0hk6x6+8QAA + + +MinLengthValidator +gb1B3r/wIkeUDgFfr7dtwwAA +4 +z9HhgfsZpk6vQG5aOdZBKQAA +gPUSt+fcikOaoH+AAheLzwAA +uOs4rEOv0UykmXnKX3W0ygAA +eGBKj40IZEGUCiX4P1z1jAAA +1 +SVsn2qUKTEmmF2QmMwcJnAAA + + + +J0JbQTHSq0yi13n61FmjzgAA +XjBwLw9OjEmKJ4KD8B58wgAA +WfkxoUbZqUOof1sQP1YufAAA +4 +5zFd1aBYUEiaDAk+OIT1vwAA +Q1EVGEa+gEGBTfHRPHeyQwAA +V3kkj8+ppU2uUukKHuY5HAAA +DMtW4jIk1EGOUomDvZBeRQAA + + +J0JbQTHSq0yi13n61FmjzgAA +w1x85nyRiUi3HLBob1jwlQAA +WfkxoUbZqUOof1sQP1YufAAA +4 +9YkaGi+Za0asQQTIGIZsJAAA +/ISe8VXAX0C5S5zwkxof5AAA +lt3cB7/kRUiQtDWrTE6mSwAA +AUHGhTx7YkSkeWhJgHdmLwAA + + +cone.validation.builtinvalidators.implml +J0JbQTHSq0yi13n61FmjzgAA +1 +oyJAaWjr+06Ztadvt0qcowAA +1 + +DuplicateTempFeatureRefValidator +Md0YIXCoWEGWJR7Ev5Wv5AAA +4 +1HH9DFhjeUaISb6w7/0iHwAA +LQOwUJ3q3U2h79vr6vuJrAAA +yZanADMD1kWito+AdZun4AAA +08EckAooiE+rkMKGjX/75wAA +1 +SYK6JJaoy0SMuQ+WSY9s/QAA + + + +J0JbQTHSq0yi13n61FmjzgAA +dtL6oUxsS0aPIWsKeupmrwAA +w1x85nyRiUi3HLBob1jwlQAA +4 +p+vZY5sJc0C6ZbH9zCH27wAA +OisbfBnQfEaKRdVx11hhYQAA +LkcpLPU5cUe8GPCArFisOQAA +7u2KWJKsX0Cfd7ZbbmNPMQAA + + + +Model1_ +UgzTZtXBekmk2L7FzuhqeQAA +1 + +ExceptionHierarchy +k3+1z5eSS0aCc7wycfchUAAA + +Vg1IlfHoukmfbJx8/sW/jgAA +35 + +clMaroon +$00B9FFFF +228 +84 +93 +95 +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +1 +ConeException + + +False + + +False + + + +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +False +CpCtdq7WY0mJ2Yw3xLfP6wAA + + + +clMaroon +$00B9FFFF +320 +264 +80 +43 +WWb6aySf10m9HwLKW3GB1QAA + + +1 +ParseError + + +False + + +False + + + +WWb6aySf10m9HwLKW3GB1QAA + + +WWb6aySf10m9HwLKW3GB1QAA + + +False +WWb6aySf10m9HwLKW3GB1QAA + + + +clMaroon +$00B9FFFF +344 +340 +91 +43 +7RmjflOgQEaQYY1KEcdIdwAA + + +1 +XmlParseError + + +False + + +False + + + +7RmjflOgQEaQYY1KEcdIdwAA + + +7RmjflOgQEaQYY1KEcdIdwAA + + +False +7RmjflOgQEaQYY1KEcdIdwAA + + + +clMaroon +$00B9FFFF +364 +428 +110 +43 +Cw3u9C6Qt0iw1URnTduBSQAA + + +1 +ImplmlParseError + + +False + + +False + + + +Cw3u9C6Qt0iw1URnTduBSQAA + + +Cw3u9C6Qt0iw1URnTduBSQAA + + +False +Cw3u9C6Qt0iw1URnTduBSQAA + + + +clMaroon +$00B9FFFF +228 +428 +109 +43 +9WnQ1vjaiU+SCF/1UtuV2AAA + + +1 +ConfmlParseError + + +False + + +False + + + +9WnQ1vjaiU+SCF/1UtuV2AAA + + +9WnQ1vjaiU+SCF/1UtuV2AAA + + +False +9WnQ1vjaiU+SCF/1UtuV2AAA + + + +clMaroon +$00B9FFFF +381,340;367,306 +BVm0I2jH00SRoMbHM39nRgAA +8gEuzA+nTkK36m0ICWvjogAA +P7XYUAivPkyiZfqkmJZTdQAA + +False +1.5707963267949 +15 +BVm0I2jH00SRoMbHM39nRgAA + + +False +1.5707963267949 +30 +BVm0I2jH00SRoMbHM39nRgAA + + +False +-1.5707963267949 +15 +BVm0I2jH00SRoMbHM39nRgAA + + + +clMaroon +$00B9FFFF +411,428;396,382 +LLUDbllKq02VrT7YfbfAtwAA +P7XYUAivPkyiZfqkmJZTdQAA +HaeqtHPbakqRfaLbF6CwpwAA + +False +1.5707963267949 +15 +LLUDbllKq02VrT7YfbfAtwAA + + +False +1.5707963267949 +30 +LLUDbllKq02VrT7YfbfAtwAA + + +False +-1.5707963267949 +15 +LLUDbllKq02VrT7YfbfAtwAA + + + +clMaroon +$00B9FFFF +308,428;364,382 +gpkLumrZqE2iroonUSQ5qwAA +P7XYUAivPkyiZfqkmJZTdQAA +dwomj5YP7kGwFoltp6sFMgAA + +False +1.5707963267949 +15 +gpkLumrZqE2iroonUSQ5qwAA + + +False +1.5707963267949 +30 +gpkLumrZqE2iroonUSQ5qwAA + + +False +-1.5707963267949 +15 +gpkLumrZqE2iroonUSQ5qwAA + + + +clMaroon +$00B9FFFF +136 +260 +160 +43 +LYT5nNubLU21hr+9lFCjagAA + + +1 +XmlSchemaValidationError + + +False + + +False + + + +LYT5nNubLU21hr+9lFCjagAA + + +LYT5nNubLU21hr+9lFCjagAA + + +False +LYT5nNubLU21hr+9lFCjagAA + + + +clMaroon +$00B9FFFF +468 +112 +101 +121 +nW6zFgSSY0WITaYT3YtvmQAA + + +1 +Problem + + +False + + +False + + + +nW6zFgSSY0WITaYT3YtvmQAA + + +nW6zFgSSY0WITaYT3YtvmQAA + + +False +nW6zFgSSY0WITaYT3YtvmQAA + + + +clMaroon +$00B9FFFF +72 +124 +125 +23 +Problem type: generic + + + +clMaroon +$00B9FFFF +492 +400 +87 +68 +Problem type: +xml +xml.confml +xml.implml + + + +clMaroon +$00B9FFFF +492 +488 +150 +30 +Problem type: model.implml + + + +clMaroon +$00B9FFFF +108 +524 +153 +30 +Problem type: model.confml + + + +clMaroon +$00B9FFFF +96 +320 +91 +53 +Problem type: +schema.confml +schema.implml + + + +clMaroon +$00B9FFFF +432 +12 +254 +68 +Example Problem object: +msg = AttributeError: 'object' has no attribute 'x' +line = None +type = generic + + + +clMaroon +$00B9FFFF +596 +344 +218 +68 +Example Problem object: +msg = no element found: line 1, column 0 +line = 1 +type = xml + + + +clMaroon +$00B9FFFF +232 +12 +90 +43 +rf6UykFPpkeu7c421sgazQAA + + +1 +Exception + + +False + + +False + + + +rf6UykFPpkeu7c421sgazQAA + + +rf6UykFPpkeu7c421sgazQAA + + +False +rf6UykFPpkeu7c421sgazQAA + + + +clMaroon +$00B9FFFF +275,84;276,54 +XStsjSJBDk+s2L22GVmGfQAA +ycmoHebIUkeHupzKOsY0GgAA +xtxslIAJy0CgGPVXL9z0lwAA + +False +1.5707963267949 +15 +XStsjSJBDk+s2L22GVmGfQAA + + +False +1.5707963267949 +30 +XStsjSJBDk+s2L22GVmGfQAA + + +False +-1.5707963267949 +15 +XStsjSJBDk+s2L22GVmGfQAA + + + +clMaroon +$00B9FFFF +191,302;171,320 +w/KYdX2JD0akKYHVVWzOFwAA +4MOFx6CJ7E+9t6vpLk2hfAAA + + +clMaroon +$00B9FFFF +432,382;492,412 +upmGcLte/EODbeZ/V/XS3AAA +P7XYUAivPkyiZfqkmJZTdQAA + + +clMaroon +$00B9FFFF +259,470;199,524 +6py8ZMKbPkGRCatUH8+yJgAA +dwomj5YP7kGwFoltp6sFMgAA + + +clMaroon +$00B9FFFF +473,469;527,488 +ESA/vgQhRkavFLeS7xjUTgAA +HaeqtHPbakqRfaLbF6CwpwAA + + +clMaroon +$00B9FFFF +608 +152 +153 +68 +The Problem class offers a +class method for creating a +Problem object based on an +exception + + + +clMaroon +$00B9FFFF +568,176;608,179 +uljCIGZb00u9fKL/uJvnCQAA +Xf++UZDQF0KMRcUTaXRTRQAA + + +clMaroon +$00B9FFFF +464 +248 +215 +83 +A Problem can be created from +any exception, but if the exception class +inherits ConeException, it may contain +more relevant information than a +regular exception + + + +clMaroon +$00B9FFFF +545,232;552,248 +aaMMwnwWZE+gAFJiCuYz9gAA +Xf++UZDQF0KMRcUTaXRTRQAA + + +clMaroon +$00B9FFFF +321,35;432,40 +pE1PBoTUuEihwSO/6zZ1xQAA +ycmoHebIUkeHupzKOsY0GgAA + + +clMaroon +$00B9FFFF +434,363;596,371 +WrkAc4o+9Em99gEWWKk3RQAA +P7XYUAivPkyiZfqkmJZTdQAA + + +clMaroon +$00B9FFFF +416 +524 +96 +43 +0F4w8SQAhU6PQs5Ym0CzEAAA + + +1 +CrmlParseError + + +False + + +False + + + +0F4w8SQAhU6PQs5Ym0CzEAAA + + +0F4w8SQAhU6PQs5Ym0CzEAAA + + +False +0F4w8SQAhU6PQs5Ym0CzEAAA + + + +clMaroon +$00B9FFFF +453,524;428,470 +B+b9kyKZoUiNPA0amRmuuwAA +HaeqtHPbakqRfaLbF6CwpwAA +ciGDbr0BfUil+uQUIDeXQQAA + +False +1.5707963267949 +15 +B+b9kyKZoUiNPA0amRmuuwAA + + +False +1.5707963267949 +30 +B+b9kyKZoUiNPA0amRmuuwAA + + +False +-1.5707963267949 +15 +B+b9kyKZoUiNPA0amRmuuwAA + + + +clMaroon +$00B9FFFF +548 +532 +173 +30 +Problem type: model.implml.crml + + + +clMaroon +$00B9FFFF +511,545;548,545 +SEQV+AMRRkakyiujQzFiDwAA +ciGDbr0BfUil+uQUIDeXQQAA + + +clMaroon +$00B9FFFF +223,260;255,178 +qQ54GGA4DEWmPw3Ix0jbCQAA +xtxslIAJy0CgGPVXL9z0lwAA +4MOFx6CJ7E+9t6vpLk2hfAAA + +False +1.5707963267949 +15 +qQ54GGA4DEWmPw3Ix0jbCQAA + + +False +1.5707963267949 +30 +qQ54GGA4DEWmPw3Ix0jbCQAA + + +False +-1.5707963267949 +15 +qQ54GGA4DEWmPw3Ix0jbCQAA + + + +clMaroon +$00B9FFFF +347,264;300,178 +hrAhTmhhzUqPv4OZuUD93AAA +xtxslIAJy0CgGPVXL9z0lwAA +8gEuzA+nTkK36m0ICWvjogAA + +False +1.5707963267949 +15 +hrAhTmhhzUqPv4OZuUD93AAA + + +False +1.5707963267949 +30 +hrAhTmhhzUqPv4OZuUD93AAA + + +False +-1.5707963267949 +15 +hrAhTmhhzUqPv4OZuUD93AAA + + + + +16 + +ConeException +k3+1z5eSS0aCc7wycfchUAAA +4 +xtxslIAJy0CgGPVXL9z0lwAA +RluVbyxCt0eQNOSNQk/mOAAA +vk1ty4gEUkOI0VMbKTvtuAAA +3jNopHqYBUSqUDjX1lLAngAA +1 +XStsjSJBDk+s2L22GVmGfQAA +2 +qQ54GGA4DEWmPw3Ix0jbCQAA +hrAhTmhhzUqPv4OZuUD93AAA +4 + +lineno +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +desc +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +problem_type +CpCtdq7WY0mJ2Yw3xLfP6wAA + + +file +CpCtdq7WY0mJ2Yw3xLfP6wAA + + + +ParseError +k3+1z5eSS0aCc7wycfchUAAA +4 +8gEuzA+nTkK36m0ICWvjogAA +r+Z/xX5IGEqLzb6SNdTfjAAA +ysZRQWJOnUKg77Wyu8QqowAA +ykLLApl4X0GrGo5gT/GYxgAA +1 +hrAhTmhhzUqPv4OZuUD93AAA +1 +BVm0I2jH00SRoMbHM39nRgAA + + +XmlParseError +k3+1z5eSS0aCc7wycfchUAAA +4 +P7XYUAivPkyiZfqkmJZTdQAA +P+xdKH0iJk+BKxNaC/XksQAA +yYyOQgqeC0OhH+tV8BkOzQAA +027y9BBw1Ey4+cWdxjA6YAAA +1 +BVm0I2jH00SRoMbHM39nRgAA +2 +LLUDbllKq02VrT7YfbfAtwAA +gpkLumrZqE2iroonUSQ5qwAA + + +ImplmlParseError +k3+1z5eSS0aCc7wycfchUAAA +4 +HaeqtHPbakqRfaLbF6CwpwAA +PGpsrNfvsES6ELZtPdnjDQAA +PjQLjDTFXUKcCeZZ9KvnVAAA +BwFC2YYWrkqriY5YQ79YOAAA +1 +LLUDbllKq02VrT7YfbfAtwAA +1 +B+b9kyKZoUiNPA0amRmuuwAA + + +ConfmlParseError +k3+1z5eSS0aCc7wycfchUAAA +4 +dwomj5YP7kGwFoltp6sFMgAA +jDNhce0FjkCT+X8T2sj7jgAA +bGGyEwnscE6wXcks12dpygAA +HQvspPLLBkKpV7E7VJXw5QAA +1 +gpkLumrZqE2iroonUSQ5qwAA + + +k3+1z5eSS0aCc7wycfchUAAA +7RmjflOgQEaQYY1KEcdIdwAA +WWb6aySf10m9HwLKW3GB1QAA +4 +DEzFmZHWVkiVKVUlFGwr5wAA +/zt+BmkJbk+chHMIAbJzqwAA +1eIkm9jR80uLOi1Y+t12mgAA +VwvCh8vDck+wTVaOAHHCnAAA + + +k3+1z5eSS0aCc7wycfchUAAA +Cw3u9C6Qt0iw1URnTduBSQAA +7RmjflOgQEaQYY1KEcdIdwAA +4 +1xq22E+bLkGOtw6Io0Y6wAAA +FfbUNjmFokylSXVU5+M71QAA +Pl72SYHpc0u2FANSnb80PQAA +KUN4dttJJki7GZhFn7yfAAAA + + +k3+1z5eSS0aCc7wycfchUAAA +9WnQ1vjaiU+SCF/1UtuV2AAA +7RmjflOgQEaQYY1KEcdIdwAA +4 +QaUC3xuE6kO01J9qUWDYjAAA +Lh8b67cFIE2AMq1mE7zVuAAA +sS12Nr1Xc0CezbuWSHeXmAAA +IxYe2zQoG0CC0N8xyyiXaQAA + + +XmlSchemaValidationError +k3+1z5eSS0aCc7wycfchUAAA +4 +4MOFx6CJ7E+9t6vpLk2hfAAA +pKg3xC3EoECOqH1DKTcw1gAA +0IN/57AxKkW9S1a24KVqrwAA +HfxuFaSr+kWSC9RMs2DGrgAA +1 +qQ54GGA4DEWmPw3Ix0jbCQAA + + +Problem +k3+1z5eSS0aCc7wycfchUAAA +4 +Xf++UZDQF0KMRcUTaXRTRQAA +xGJmIZm9LUmVsEUJd0LzcQAA +ksBzPPYQuEmMjRKqH71jMAAA +DI543AOKrUuhdWGU4HBgswAA +1 + +from_exception +skClassifier +nW6zFgSSY0WITaYT3YtvmQAA + +5 + +msg +nW6zFgSSY0WITaYT3YtvmQAA + + +line +nW6zFgSSY0WITaYT3YtvmQAA + + +file +nW6zFgSSY0WITaYT3YtvmQAA + + +severity +nW6zFgSSY0WITaYT3YtvmQAA + + +type +nW6zFgSSY0WITaYT3YtvmQAA + + + +Exception +k3+1z5eSS0aCc7wycfchUAAA +4 +ycmoHebIUkeHupzKOsY0GgAA +kaDas08xSUSwaF3Qo0nanwAA +vdo9HscXSkeF0cX4MnGddgAA +NhZBPUXvf0iw2VkM+GMpnAAA +1 +XStsjSJBDk+s2L22GVmGfQAA + + +k3+1z5eSS0aCc7wycfchUAAA +CpCtdq7WY0mJ2Yw3xLfP6wAA +rf6UykFPpkeu7c421sgazQAA +4 +dSXjIJ9YUE2CX+onbmfhGgAA +yoUriE7jSEeYmCUlxujIIwAA +AZ60xT26CEKYZqbO16ljaAAA +b+RDR1+nHUG8DCzD022LUQAA + + +CrmlParseError +k3+1z5eSS0aCc7wycfchUAAA +4 +ciGDbr0BfUil+uQUIDeXQQAA +CPVoTDN5oEGoCR2LZrM2KwAA +5TxAVUuD/06c2nmBaYwLRAAA +szEqhCsiVE65lCiPPYS8OwAA +1 +B+b9kyKZoUiNPA0amRmuuwAA + + +k3+1z5eSS0aCc7wycfchUAAA +0F4w8SQAhU6PQs5Ym0CzEAAA +Cw3u9C6Qt0iw1URnTduBSQAA +4 +g9lNCCdLNE2rVWwg8oKFlQAA +qQxCbD8bPkm1RzefpboXbwAA +knY2vp+HL02Rl2Fy2DYaOAAA +NfHUtnHoW06wP1ZpBMH2dgAA + + +k3+1z5eSS0aCc7wycfchUAAA +LYT5nNubLU21hr+9lFCjagAA +CpCtdq7WY0mJ2Yw3xLfP6wAA +4 +Y3Nmw6b48ES7XMYmOgDkcQAA +BV6s2EtNyU2NIwJrOCKEsgAA +f0AOhRp8y0aAenoFW5fAEwAA +xeqe/1TQFUSBF0zLR7uPSAAA + + +k3+1z5eSS0aCc7wycfchUAAA +WWb6aySf10m9HwLKW3GB1QAA +CpCtdq7WY0mJ2Yw3xLfP6wAA +4 +lzTahw8af0mMhES17c0s7gAA +a5ldPk/cF0SEFRsmjO7EzQAA +ujixESozM0WHAPa6R9/0NAAA +EcDaxMOyA0ecgSslQ7x4lwAA + + + +Model2 +UgzTZtXBekmk2L7FzuhqeQAA +1 + +ClassDiagram1 +YIOeIf6CZkqa1NWYPAT9yQAA + +U5ypMcL5SkK1kpJjE1zJ7QAA +7 + +clMaroon +$00B9FFFF +208 +96 +205 +69 +TRhtGYancUSTVzgzudt8vgAA + + +1 +ImplmlParseContext + + +False + + +False + + + +TRhtGYancUSTVzgzudt8vgAA + + +TRhtGYancUSTVzgzudt8vgAA + + +False +TRhtGYancUSTVzgzudt8vgAA + + + +clMaroon +$00B9FFFF +292 +248 +205 +69 +mvuvaoq69U+8RTdsphq0WAAA + + +1 +ValidationImplmlParseContext + + +False + + +False + + + +mvuvaoq69U+8RTdsphq0WAAA + + +mvuvaoq69U+8RTdsphq0WAAA + + +False +mvuvaoq69U+8RTdsphq0WAAA + + + +clMaroon +$00B9FFFF +375,248;329,164 +eT3WFDjFcUOC0uUTMJC3VwAA +nUTauj7GFUujlHPXz/NkOwAA +j5JHJNBwdUiknDiaUgPscQAA + +False +1.5707963267949 +15 +eT3WFDjFcUOC0uUTMJC3VwAA + + +False +1.5707963267949 +30 +eT3WFDjFcUOC0uUTMJC3VwAA + + +False +-1.5707963267949 +15 +eT3WFDjFcUOC0uUTMJC3VwAA + + + +clMaroon +$00B9FFFF +456 +76 +224 +68 +The parse context defines how exceptions +and problems encountered during parsing +are handled. The default context simply +logs all exceptions and problems. + + + +clMaroon +$00B9FFFF +532 +200 +195 +53 +When validating, a parse context +that collects a list of Problem objects +is used. + + + +clMaroon +$00B9FFFF +496,258;532,249 +qrZ2QIGHG0Cn+sYe8SCjGgAA +j5JHJNBwdUiknDiaUgPscQAA + + +clMaroon +$00B9FFFF +412,122;456,118 +u9kalNIVQUyZsb7Z40SkkgAA +nUTauj7GFUujlHPXz/NkOwAA + + + +3 + +ImplmlParseContext +YIOeIf6CZkqa1NWYPAT9yQAA +4 +nUTauj7GFUujlHPXz/NkOwAA +WVzqaOkVYk6M5VmRJT2SdwAA +12iPO0ZV/ECC+ZxBdww9NwAA +P389F+FIr0u60EVDOuy9QgAA +1 +eT3WFDjFcUOC0uUTMJC3VwAA +2 + +handle_exception +TRhtGYancUSTVzgzudt8vgAA +2 + +exception +kj0ZrAVvD0yl4xHAdFN8SQAA + + +filename +kj0ZrAVvD0yl4xHAdFN8SQAA + + + +handle_problem +TRhtGYancUSTVzgzudt8vgAA +1 + +problem +ISpOCfw1GkONuBx7w9SXZQAA + + + + +ValidationImplmlParseContext +YIOeIf6CZkqa1NWYPAT9yQAA +4 +j5JHJNBwdUiknDiaUgPscQAA +Hdc7mB53mUif8sFjpKqYdAAA +eAOCvVCWdEW+UXQzOgQ6gAAA +KXQDxUmITEiHMMcW/RM4jQAA +1 +eT3WFDjFcUOC0uUTMJC3VwAA +2 + +handle_exception +mvuvaoq69U+8RTdsphq0WAAA +2 + +exception +evp+p65t7U6mV5QdBdOpTAAA + + +filename +evp+p65t7U6mV5QdBdOpTAAA + + + +handle_problem +mvuvaoq69U+8RTdsphq0WAAA +1 + +problem +7bCi/mTMJUWdBc/nL9kodgAA + + + + +YIOeIf6CZkqa1NWYPAT9yQAA +mvuvaoq69U+8RTdsphq0WAAA +TRhtGYancUSTVzgzudt8vgAA +4 +0+P5ulM6CUK32H3J4trkIwAA +zdHGyXIYQkei12PmlUOtvAAA +fd8XAhF0f0an5zXFhtyYvQAA +MsBk9Z2Ib0GEa5SGERK3hAAA + + + + + diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/plugin-interface.rst --- a/configurationengine/doc/plugins/dev-plugin/plugin-interface.rst Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/doc/plugins/dev-plugin/plugin-interface.rst Tue Aug 10 14:29:28 2010 +0300 @@ -3,7 +3,11 @@ Plug-in interface ================= -A ConE plug-in has two points for interfacing with ConE: +Implementation languages +------------------------ + +A ConE plug-in that adds support for an implementation language has two points +for interfacing with ConE: #. Reader classes that derive from ``cone.public.plugin.ReaderBase`` . These classes define supported Implementation Markup Languages (i.e. supported XML namespaces) @@ -16,6 +20,9 @@ .. image:: plugin_classes.jpg +For more information on the classes see the +`ConE API epydoc <../../epydoc/cone.public.plugin-module.html>`_. + ConE generation can be seen to consist of two phases, implementation parsing and output generation: @@ -38,7 +45,7 @@ - Output is generated using each implementation set. For each implementation set: - The ``generation_context`` variable of each implementation instance is set - (this context contains generation-scope information implementations instances may use) + (this context contains generation-scope information implementation instances may use) - The ``generate()`` method of each instance is called - The ``post_generate()`` method of each instance is called @@ -63,138 +70,48 @@ 10-11 Output generation methods are called ====== ======================================================================== -Plug-in interface class source ------------------------------- + +.. _plugin-howto-plugin-interface-validation: -The following source listings show the most important parts of the ``ImplReader`` -and ``ImplBase`` classes from a plug-in's point of view: - -.. code-block:: python +Validation +---------- - class ReaderBase(object): - """ - Base class for implementation readers. - - Each reader class supports one XML namespace, from which it reads an implementation - instance. - - The method for parsing an implementation (read_impl()) is given an ElementTree - XML element as the root from which to parse the implementation. The plug-in - machinery handles each XML file so that the correct reader class is used to read - the implementations from XML elements based on the namespaces. - """ - - # The XML namespace supported by the implementation reader. - # Should be something like "http://www.xyz.org/xml/1". - # Can also be None, in which case the reader will not be used - # (this can be useful for defining base classes for e.g. readers - # for different versions of an implementation). - NAMESPACE = 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 - # inside an implementation (e.g. XInclude) - IGNORED_NAMESPACES = [] - - # Supported implementation file extensions. - # Sub-classes can override this to add new supported file extensions - # if necessary. The file extensions simply control whether implementations - # are attempted to be read from a file or not. - # Note that the extensions are case-insensitive. - FILE_EXTENSIONS = ['implml'] - - @classmethod - def read_impl(cls, resource_ref, configuration, doc_root): - """ - Read an implementation instance from the given element tree. - - @param resource_ref: Reference to the resource in the configuration in - which the given document root resides. - @param configuration: The configuration used. - @param doc_root: The document root from which to parse the implementation. - @return: The read implementation instance, or None. - """ - raise exceptions.NotSupportedException() +.. note:: + + See also :ref:`validation-overview` -.. code-block:: python +The ConE plug-in interface allows for the extension of ConfML and ImplML validation. +In the same way as support for new implementation languages can be provided +by exposing implementation reader classes via egg entry points, validation +can be extended by exposing validator classes. + +Validation happens roughly in the following manner: - class GenerationContext(object): - """ - Context object that can be used for passing generation-scope - data to implementation instances. - """ - - def __init__(self, tags={}): - # The tags used in this generation context - # (i.e. the tags passed from command line) - self.tags = tags - - # A dictionary that implementation instances can use to - # pass any data between each other - self.impl_data_dict = {} - -.. code-block:: python +1. A list of *validator classes* is obtained through some means. In practice + this usually means finding all validator classes, and then filtering them + down to those that produce the problems that we are interested in. +2. A *validation context* is created. This contains everything associated with + the validation, and here all found problems are reported. All validators + have access to it. +3. For each entity (configuration or implementation instance) that is being + validated, an instance of each validator class is created and invoked. - class ImplBase(object): - """ - Base class for any confml implementation. - """ - - # Identifier for the implementation type, used e.g. in .cfg files. - # Should be a string like e.g. 'someml'. - IMPL_TYPE_ID = None - - # Defines the default invocation phase for the implementation. - # The default is used if the phase is not explicitly set in the - # ImplML file or manually overridden by calling set_invocation_phase() - DEFAULT_INVOCATION_PHASE = None - - def __init__(self,ref, configuration): - """ - Create a ImplBase object - @param ref : the ref to the Implml file resource. - @param configuration : the Configuration instance for the - configuration data. - """ - self._settings = None - self.ref = ref - self.index = None - self.configuration = configuration - self.output_root = self.settings.get('output_root','output') - self.output_subdir = self.settings.get('output_subdir','') - self.plugin_output = self.settings.get('plugin_output','') - - self.generation_context = None - self._tags = None - self._invocation_phase = None - self._tempvar_defs = [] +This process is nearly the same for ConfML and ImplML validation, only some +details about the validation context and the entities being validated are +different, as well as the fact ConfML validation on the entire configuration, +whereas ImplML validation happens on individual implementation instances, with +a few exceptions. + +The following diagram illustrates ImplML validation: + +.. image:: impl-validation-classes.jpg - def generate(self): - """ - Generate the given implementation. - @return: - """ - raise exceptions.NotSupportedException() - - def post_generate(self): - """ - Called when all normal generation has been done. - - @attention: This is a temporary method used for implementing cenrep_rfs.txt generation. - """ - pass - - def list_output_files(self): - """ - Return a list of output files as an array. - """ - raise exceptions.NotSupportedException() - - 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 None +The following diagram illustrates ConfML validation: + +.. image:: confml-validation-classes.jpg + +For more information on the classes involved in validate see the +ConE API epydoc for `cone.validation.implmlvalidation <../../epydoc/cone.validation.implmlvalidation-module.html>`_ +and `cone.validation.confmlvalidation <../../epydoc/cone.validation.confmlvalidation-module.html>`_. +Also the built-in validators in the package `cone.validation.builtinvalidators <../../epydoc/cone.validation.builtinvalidators-module.html>`_ +can serve as examples. \ No newline at end of file diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/plugin_classes.jpg Binary file configurationengine/doc/plugins/dev-plugin/plugin_classes.jpg has changed diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/validation-example-plugin.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/dev-plugin/validation-example-plugin.rst Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,88 @@ +.. _validation-plugin-howto-example-plugin: + +Example ConfML validation plug-in +================================= + +The example plug-in implements a simple ConfML validator class, and so demostrates +how ConfML validation can be extended by plug-ins. + +The extra validation in this case is as follows: we have a requirement that if +a string-type ConfML setting's reference starts with ``FOO_``, its value +should also contain the string ``foo``. For example, consider the following +file: + +.. code-block :: xml + :linenos: + + + + + + + + + + + foo bar + abc foo + abc123 + + + + +Here two settings are prefixed with ``FOO_``, but only one of them has ``foo`` +in its value, thus our custom validator should report a warning for the value +on line 12. + +Directory structure +------------------- + +- ``plugins/`` - Root directory for all ConE plug-in sources + - ``example/`` - Example plug-in package directory + - ``ConeExampleValidatorPlugin/`` - Source for the example validator plug-in + - ``examplevalidatorplugin/`` - Module directory containing all plug-in code + - ``tests/`` - Unit tests and test data for the plug-in + - ``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_validation.py`` - File containing test cases + - ``__init__.py`` - Plug-in module initialization file + - ``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`` + +Plug-in code +------------ + +validators.py +............. + +This file defines the validator class. The validator simply goes through all +``ConfmlStringSetting`` instances in the configuration and checks their values. + +.. literalinclude:: /../source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/validators.py + :linenos: + + +unittest_validation.py +...................... + +The tests for the plug-in simply contain one test case that tests the validator +with the example ConfML file shown earlier, using the ``assert_problem_list_equals_expected()`` +method provided by the ``testautomation`` module. + +.. literalinclude:: /../source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/unittest_validation.py + :linenos: + + +Plug-in packaging +----------------- + +The file ``setup.py`` handles the packaging of the plug-in into an egg file. + +The most important thing here is the plug-in's entry point info. The list +of validator classes provided by the plug-in must be specified as an entry +point. The entry point group in this case is ``cone.plugins.confmlvalidators``. + +.. literalinclude:: /../source/plugins/example/ConeExampleValidatorPlugin/setup.py + :linenos: diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/validation-plugin-index.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/dev-plugin/validation-plugin-index.rst Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,13 @@ +.. _validation-plugin-howto: + +How to create a ConfML validation plug-in for ConE +================================================== + +This page contains a description of +an example plug-in intended to be used as a template for creating new ConfML validation plug-in. +It is recommended to read also about the :ref:`plug-in interface ` + +.. toctree:: + :maxdepth: 3 + + validation-example-plugin diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/general.rst --- a/configurationengine/doc/plugins/general.rst Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/doc/plugins/general.rst Tue Aug 10 14:29:28 2010 +0300 @@ -55,7 +55,7 @@ - + @@ -71,7 +71,7 @@ - The container is in http://www.symbianfoundation.org/xml/implml/1, the root element of implml namespace must always be container - The ruleml is in http://www.s60.com/xml/ruleml/2 - - The content is in xmlns="http://www.s60.com/xml/content/3" + - The content is in xmlns="http://www.s60.com/xml/content/2" When reading the implementation file, ConE checks the document root and its namespace to find out from namespace to start parsing. @@ -157,7 +157,7 @@ - + CustomSettings.StartupSoundFile.localPath configures @@ -167,15 +167,15 @@ - - + + - + @@ -291,7 +291,7 @@ - + X.Y configures X.Z = X.Y @@ -310,7 +310,7 @@ - + X.Y configures X.Z = X.Y @@ -356,10 +356,10 @@ .. code-block:: xml - - - - + + + + Tags can also get their values from ConfML settings, which can be referenced in the usual way: @@ -537,7 +537,7 @@ - + @@ -610,12 +610,10 @@ - - - + @@ -623,18 +621,4 @@ -In the above example the content is copied to \epoc32\data\widgets\some_dir\text.wgz. - - -.. rubric:: Footnotes - -.. [#multi-content-note] In this case the run-time behavior would still be same; ContentML - allows multiple ``output`` elements. However, this might not be the case for all - implementation languages. - -.. [#legacy-implml-root-name-note] The specifications for the legacy implementation - languages CRML and GenConfML do give the root element names, and say that each - implementation must be in its own crml/gcfml file. - It is recommended to stick to this convention for these two implementation languages - also in the future. Indeed, using them in a multi-implementation file has not been - tested and may not even work correctly. +In the above example the content is copied to \\epoc32\\data\\widgets\\some_dir\\text.wgz. diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/examples/bmp_and_optional_mask.imageml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/imageml-plugin/examples/bmp_and_optional_mask.imageml Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/examples/multi_input.imageml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/imageml-plugin/examples/multi_input.imageml Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/examples/simple.imageml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/imageml-plugin/examples/simple.imageml Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/examples/with_refs.imageml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/imageml-plugin/examples/with_refs.imageml Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,21 @@ + + + + + + + + + + + + \ No newline at end of file diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/imageml-example-project.zip Binary file configurationengine/doc/plugins/imageml-plugin/imageml-example-project.zip has changed diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/imageml-plugin.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/doc/plugins/imageml-plugin/imageml-plugin.rst Tue Aug 10 14:29:28 2010 +0300 @@ -0,0 +1,214 @@ +User guide for ImageML Plugin usage in ConE +=========================================== + +Introduction +------------ +This page describes how to use the ConE ImageML plug-in. +The plug-in defines the ImageML Implementation Markup Language, which provides +image conversion from BMP to MBM and SVG to MIF using the ``mifconv`` and +``bmconv`` tools. + +XML namespace and file extension +-------------------------------- + +- Namespace: ``http://www.s60.com/xml/imageml/1`` +- File extension: ``imageml`` + +ImageML elements +---------------- + +The ImageML XML element model is drawn out as a UML class diagram below: + + .. image:: imageml.jpg + +output +^^^^^^ + +The ``output`` element defines an output file for image conversion. A single +ImageML implementation may contain multiple ``output`` elements. + +**Attributes** + + * *file* - Output file location, for example ``resource/apps/image.mbm``. + The output tool used to perform the conversion is deduced from the file + extension: bmconv for .mbm and mifconv for .mif. The file location can + also come from a ConfML setting using the ``${}`` notation. + * *tool* - Override for the path to the tool to use. This is mainly useful + for testing, in production use the bmconv and mifconv tools should be in PATH. + * *palette* - Specifies a .pal file to use for MBM conversion. + * *tooldir* - Override for the location of the bmconv and mifconv tools. + This is mainly useful for testing, in production use the bmconv and mifconv + tools should be in PATH. + * *extraparams* - Optional attribute that can be used to pass extra parameters + for tool. For details see bmconv and mifconv documentation. E.g. "/V3" defines + for mifconv the format version of SVG binary conversion. If not defined value + forces Svgtbinencode to use the default platform specific value. + Options for mifconv /V parameter are: + +.. list-table:: + + - - *Value* + - *Format type* + - - /V1 + - BGR / float encoding + - - /V2 + - BGR / fixed point encoding + - - /V3 + - RGB / fixed point encoding + - - /V4 + - RGB / float encoding + - - /V5 + - NVG encoding + + +**Example** + +.. code-block:: xml + + + + + + + + + + + +input +^^^^^ + +The ``input`` element defines a single input file for image conversion, or a +directory from which input files are selected based on regular expression +patterns. One ``output`` element may contain multiple ``input`` elements. + +An input element must specify a file using the ``file`` attribute or a directory +using the ``dir`` attribute, but not both. + +**Attributes** + + * *file* - Input file from the configuration project content. Can also be + a ConfML setting reference using the ``${}`` notation. + * *dir* - Directory for input files from the configuration project content. + Can also be a ConfML setting reference using the ``${}`` notation. + * *depth* - Color depth switch passed to bmconv for the file(s) specified by + the current ``input`` element, does nothing if mifconv is used. + Can also be a ConfML setting reference using the ``${}`` notation. + * *optional* - If ``true``, then the input dir or file may be empty and + no error is reported. Can be used to e.g. specify an optional mask bitmap. + +**Examples** + +.. code-block:: xml + + + + + + + + + + + + + + + +include and exclude +^^^^^^^^^^^^^^^^^^^ + +The ``include`` and ``exclude`` elements specify regular expressions for +selecting input files from an input directory. + +**Attributes** + + * *pattern* - The regular expression used to include or exclude files + +**Examples** + +.. code-block:: xml + + + + + +Setting references +------------------ + +The setting references that an ImageML implementation uses are determined as +follows: + + * If any ``input`` elements contain setting references in their ``file`` + or ``dir`` attributes, those are the setting references used by the + ImageML implementation. + * If there are no setting references in those attributes, setting references + are considered to be irrelevant, and the implementation is always run + regardless of setting reference filtering. + +See the examples in the section below. + +ImageML examples +---------------- + +All the examples shown in this section can also be downloaded: + + * :download:`imageml-example-project.zip` + +You need to have bmconv and mifconv somewhere in your path for generation to +work. To generate output from the project simply run:: + + > cone generate -p imageml-example-project.zip + +Or unzip (e.g. to ``imageml-example-project``) and run:: + + > cd imageml-example-project + imageml-example-project\> cone generate + + +Simple image conversion using a single input file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: examples/simple.imageml + :language: xml + +Setting references of this implementation: None (irrelevant) + +Simple image conversion with ConfML setting references +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: examples/with_refs.imageml + :language: xml + +Setting references of this implementation: + + - ``TestSettings.ConeInputBmp.localPath`` + - ``TestSettings.IconInputSvg.localPath`` + +MBM conversion using multiple input files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: examples/multi_input.imageml + :language: xml + +Setting references of this implementation: None (irrelevant) + +MBM conversion using an optional mask file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: examples/bmp_and_optional_mask.imageml + :language: xml + +Setting references of this implementation: + + - ``TestSettings.ConeInputBmp.localPath`` + - ``TestSettings.ConeInputBmpMask.localPath`` + +FAQ +--- + +This will be updated based on the questions. + diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/imageml-plugin/imageml.jpg Binary file configurationengine/doc/plugins/imageml-plugin/imageml.jpg has changed diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/index.rst --- a/configurationengine/doc/plugins/index.rst Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/doc/plugins/index.rst Tue Aug 10 14:29:28 2010 +0300 @@ -34,11 +34,9 @@ hcrml-plugin/hcrml-plugin convertprojectplugin thememl-plugin/themelplugin + imageml-plugin/imageml-plugin ConE plug-in development ------------------------ -.. toctree:: - :maxdepth: 2 - - dev-plugin/index +* See :ref:`plugin-api` for instructions how to create a ConE plugin. diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/plugins.uml --- a/configurationengine/doc/plugins/plugins.uml Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/doc/plugins/plugins.uml Tue Aug 10 14:29:28 2010 +0300 @@ -5527,6 +5527,727 @@ I0mGM2cIbES/2vP45srj7AAA Oz6AUWlj3Ei96BpX7wdxtAAA +9 + +clMaroon +$00B9FFFF +180 +40 +93 +33 +CRuOLYF7gU2l1tg34dY6bgAA + + +1 +imageml + + +False + + +False + + + +CRuOLYF7gU2l1tg34dY6bgAA + + +False +CRuOLYF7gU2l1tg34dY6bgAA + + +False +CRuOLYF7gU2l1tg34dY6bgAA + + + +clMaroon +$00B9FFFF +168 +124 +113 +98 +CouoggW8r0OOBNQ9jNxO6wAA + + +1 +output + + +False + + +False + + + +CouoggW8r0OOBNQ9jNxO6wAA + + +False +CouoggW8r0OOBNQ9jNxO6wAA + + +False +CouoggW8r0OOBNQ9jNxO6wAA + + + +clMaroon +$00B9FFFF +180 +260 +93 +85 +NnSa/LdMlkaJlBQz+1Y2+AAA + + +1 +input + + +False + + +False + + + +NnSa/LdMlkaJlBQz+1Y2+AAA + + +False +NnSa/LdMlkaJlBQz+1Y2+AAA + + +False +NnSa/LdMlkaJlBQz+1Y2+AAA + + + +clMaroon +$00B9FFFF +140 +404 +86 +46 +mgS5RRx5dkWAWIQMpavygAAA + + +1 +include + + +False + + +False + + + +mgS5RRx5dkWAWIQMpavygAAA + + +False +mgS5RRx5dkWAWIQMpavygAAA + + +False +mgS5RRx5dkWAWIQMpavygAAA + + + +clMaroon +$00B9FFFF +240 +404 +80 +46 +NJ7DLEDyw0+w4FnIFdtdCQAA + + +1 +exclude + + +False + + +False + + + +NJ7DLEDyw0+w4FnIFdtdCQAA + + +False +NJ7DLEDyw0+w4FnIFdtdCQAA + + +False +NJ7DLEDyw0+w4FnIFdtdCQAA + + + +clMaroon +$00B9FFFF +190,404;211,344 +0q7RIUYseEewHATv7QqdaQAA +3nJAwrIQQ02ZlQ/Rjto/1wAA +faGCnxpYz0SvcMgXl5/tzgAA + +False +1.5707963267949 +15 +0q7RIUYseEewHATv7QqdaQAA + + +False +1.5707963267949 +30 +0q7RIUYseEewHATv7QqdaQAA + + +False +-1.5707963267949 +15 +0q7RIUYseEewHATv7QqdaQAA + + +False +-0.523598775598299 +30 +epHead +aOIUpy17wEu1onMvkPLDZwAA + + +False +0.523598775598299 +30 +epTail +3PfRfm/wr02VIWBqM76erwAA + + +False +0.523598775598299 +25 +epHead +aOIUpy17wEu1onMvkPLDZwAA + + +-0.749643646812705 +21.4709105535839 +epTail +0..* +3PfRfm/wr02VIWBqM76erwAA + + +False +-0.785398163397448 +40 +epHead +aOIUpy17wEu1onMvkPLDZwAA + + +False +0.785398163397448 +40 +epTail +3PfRfm/wr02VIWBqM76erwAA + + +False +-1000 +-1000 +50 +8 +aOIUpy17wEu1onMvkPLDZwAA + + +False +-1000 +-1000 +50 +8 +3PfRfm/wr02VIWBqM76erwAA + + + +clMaroon +$00B9FFFF +270,404;244,344 +IFIQQJ7iSEO69Wh+e5lJygAA +3nJAwrIQQ02ZlQ/Rjto/1wAA +iajjxaOU7E+x5X6fMy+ongAA + +False +1.5707963267949 +15 +IFIQQJ7iSEO69Wh+e5lJygAA + + +False +1.5707963267949 +30 +IFIQQJ7iSEO69Wh+e5lJygAA + + +False +-1.5707963267949 +15 +IFIQQJ7iSEO69Wh+e5lJygAA + + +False +-0.523598775598299 +30 +epHead +M1sojijAckaHORNZ6AKvSgAA + + +False +0.523598775598299 +30 +epTail +69rEKoPGI0mo75lP5BvwtAAA + + +False +0.523598775598299 +25 +epHead +M1sojijAckaHORNZ6AKvSgAA + + +4.78795835027941 +21.4709105535839 +epTail +0..* +69rEKoPGI0mo75lP5BvwtAAA + + +False +-0.785398163397448 +40 +epHead +M1sojijAckaHORNZ6AKvSgAA + + +False +0.785398163397448 +40 +epTail +69rEKoPGI0mo75lP5BvwtAAA + + +False +-1000 +-1000 +50 +8 +M1sojijAckaHORNZ6AKvSgAA + + +False +-1000 +-1000 +50 +8 +69rEKoPGI0mo75lP5BvwtAAA + + + +clMaroon +$00B9FFFF +225,260;225,221 +POtOWRvYQ0WO9SQIvdJpeQAA +2yz5/OUBRUKzrr3xYqPQ+AAA +3nJAwrIQQ02ZlQ/Rjto/1wAA + +False +1.5707963267949 +15 +POtOWRvYQ0WO9SQIvdJpeQAA + + +False +1.5707963267949 +30 +POtOWRvYQ0WO9SQIvdJpeQAA + + +False +-1.5707963267949 +15 +POtOWRvYQ0WO9SQIvdJpeQAA + + +False +-0.523598775598299 +30 +epHead +Z/WCj9Ir1Uua8nPwAz0BOAAA + + +False +0.523598775598299 +30 +epTail +cDxLP9sd7EqSP+9VET4kGgAA + + +False +0.523598775598299 +25 +epHead +Z/WCj9Ir1Uua8nPwAz0BOAAA + + +-0.856705765824159 +19.8494332412792 +epTail +1..* +cDxLP9sd7EqSP+9VET4kGgAA + + +False +-0.785398163397448 +40 +epHead +Z/WCj9Ir1Uua8nPwAz0BOAAA + + +False +0.785398163397448 +40 +epTail +cDxLP9sd7EqSP+9VET4kGgAA + + +False +-1000 +-1000 +50 +8 +Z/WCj9Ir1Uua8nPwAz0BOAAA + + +False +-1000 +-1000 +50 +8 +cDxLP9sd7EqSP+9VET4kGgAA + + + +clMaroon +$00B9FFFF +lsRectilinear +226,124;226,72 +rbj+IedETU6G6PuTN46nBAAA +/Aq0TH5t8EiVzBQ4GkGa/AAA +2yz5/OUBRUKzrr3xYqPQ+AAA + +False +1.5707963267949 +15 +rbj+IedETU6G6PuTN46nBAAA + + +False +1.5707963267949 +30 +rbj+IedETU6G6PuTN46nBAAA + + +False +-1.5707963267949 +15 +rbj+IedETU6G6PuTN46nBAAA + + +False +-0.523598775598299 +30 +epHead +cR78ghIdUUaPftW/gFc/yAAA + + +False +0.523598775598299 +30 +epTail +sJQEHCEx7kGDl0V2tep+ewAA + + +False +0.523598775598299 +25 +epHead +cR78ghIdUUaPftW/gFc/yAAA + + +-0.950546986342061 +17.2046505340853 +epTail +0..* +sJQEHCEx7kGDl0V2tep+ewAA + + +False +-0.785398163397448 +40 +epHead +cR78ghIdUUaPftW/gFc/yAAA + + +False +0.785398163397448 +40 +epTail +sJQEHCEx7kGDl0V2tep+ewAA + + +False +-1000 +-1000 +50 +8 +cR78ghIdUUaPftW/gFc/yAAA + + +False +-1000 +-1000 +50 +8 +sJQEHCEx7kGDl0V2tep+ewAA + + + + +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 - + lambda a,b: a+b lambda 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 @@ true 1 "opt 0" "opt 2" "opt 4" + 00112233445566778899AABBCCDDEEFF @@ -57,6 +62,7 @@ true true true + 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 @@ + + + + +