Package Gnumed :: Package timelinelib :: Package features :: Package experimental :: Module experimentalfeatures
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.features.experimental.experimentalfeatures

  1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17   
 18   
 19  """ 
 20  ExperimentalFeatures is responsible for reading and storing experimental features 
 21     configuration, to and from the configuration file. 
 22     It also holds a list of available experimental features. 
 23     All experimental features are instantiated when this file is loaded. 
 24   
 25  To add a new experimental feature, do as follows: 
 26      - Create a new file in timelinelib.features.experimental, defining a class 
 27        that inherits from ExperimentalFeature and calls the parent __init__()- 
 28        function with the two arguments DISPLAY_NAME and DESCRIPTION. 
 29      - Instantiate the new experimental feature class in this file like... 
 30          NAME = NewExperimentalFeatureClass() 
 31      - Add the instantiated object to the FEATURES list in this file. 
 32      - Implement the feature logic under the condition... 
 33          if NAME.enabled(): 
 34      - If new methods are created that only are used by the new feature, 
 35        decorate these functions with @experimental_feature(NAME) 
 36  """ 
 37   
 38   
 39  from timelinelib.features.experimental.experimentalfeaturecontainersize import ExperimentalFeatureContainerSize 
 40  from timelinelib.features.experimental.experimentalfeaturenegativejuliandays import ExperimentalFeatureNegativeJulianDays 
 41  from timelinelib.features.experimental.experimentalfeatureextendedcontainerstrategy import ExperimentalFeatureExtendedContainerStrategy 
 42   
 43   
 44  EXTENDED_CONTAINER_HEIGHT = ExperimentalFeatureContainerSize() 
 45  NEGATIVE_JULIAN_DAYS = ExperimentalFeatureNegativeJulianDays() 
 46  EXTENDED_CONTAINER_STRATEGY = ExperimentalFeatureExtendedContainerStrategy() 
 47  FEATURES = (EXTENDED_CONTAINER_HEIGHT, NEGATIVE_JULIAN_DAYS, EXTENDED_CONTAINER_STRATEGY) 
 48   
 49   
50 -class ExperimentalFeatureException(Exception):
51 pass
52 53
54 -class ExperimentalFeatures(object):
55
56 - def __str__(self):
57 """ 58 Formats the configuration string for all experimental features, 59 which is a semicolon separated list of feature configurations. 60 features-configuration ::= (feature-configuration ';')* 61 feature-configuration ::= feature-name '=' ('True'|'False') 62 """ 63 collector = [] 64 for feature in FEATURES: 65 collector.append(feature.get_config()) 66 return "".join(collector)
67
68 - def get_all_features(self):
69 return FEATURES
70
72 for item in cfg_string.split(";"): 73 if "=" in item: 74 name, value = item.split("=") 75 self.set_active_state_on_feature_by_name(name.strip(), value.strip() == "True")
76
77 - def set_active_state_on_feature_by_index(self, feature_index, value):
78 FEATURES[feature_index].set_active(value)
79
80 - def set_active_state_on_feature_by_name(self, name, value):
81 for feature in FEATURES: 82 if feature.get_config_name() == name: 83 feature.set_active(value) 84 return 85 elif feature.get_display_name() == name: 86 feature.set_active(value) 87 return
88 89
90 -def experimental_feature(feature):
91 """ 92 The syntax for decorators with arguments is a bit different - the decorator 93 with arguments should return a function that will take a function and return 94 another function. So it should really return a normal decorator. 95 96 Decorator used for methods, only used by an Experimental feature. 97 The purpose of the decorator is to simplify removal of the feature 98 code if it is decided not to implement the feature. 99 Example: 100 @experimental_feature(EVENT_DONE) 101 def foo() 102 pass 103 """ 104 def deco(foo): 105 if feature not in FEATURES: 106 raise ExperimentalFeatureException("Feature '%s', not implemented" % feature.get_display_name()) 107 return foo
108 return deco 109