Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/gs/lifecycle.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 # Copyright 2013 Google Inc. | |
| 2 # | |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 4 # copy of this software and associated documentation files (the | |
| 5 # "Software"), to deal in the Software without restriction, including | |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 9 # lowing conditions: | |
| 10 # | |
| 11 # The above copyright notice and this permission notice shall be included | |
| 12 # in all copies or substantial portions of the Software. | |
| 13 # | |
| 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 20 # IN THE SOFTWARE. | |
| 21 | |
| 22 from boto.exception import InvalidLifecycleConfigError | |
| 23 | |
| 24 # Relevant tags for the lifecycle configuration XML document. | |
| 25 LIFECYCLE_CONFIG = 'LifecycleConfiguration' | |
| 26 RULE = 'Rule' | |
| 27 ACTION = 'Action' | |
| 28 DELETE = 'Delete' | |
| 29 SET_STORAGE_CLASS = 'SetStorageClass' | |
| 30 CONDITION = 'Condition' | |
| 31 AGE = 'Age' | |
| 32 CREATED_BEFORE = 'CreatedBefore' | |
| 33 NUM_NEWER_VERSIONS = 'NumberOfNewerVersions' | |
| 34 IS_LIVE = 'IsLive' | |
| 35 MATCHES_STORAGE_CLASS = 'MatchesStorageClass' | |
| 36 | |
| 37 # List of all action elements. | |
| 38 LEGAL_ACTIONS = [DELETE, SET_STORAGE_CLASS] | |
| 39 # List of all condition elements. | |
| 40 LEGAL_CONDITIONS = [AGE, CREATED_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE, | |
| 41 MATCHES_STORAGE_CLASS] | |
| 42 # List of conditions elements that may be repeated. | |
| 43 LEGAL_REPEATABLE_CONDITIONS = [MATCHES_STORAGE_CLASS] | |
| 44 | |
| 45 class Rule(object): | |
| 46 """ | |
| 47 A lifecycle rule for a bucket. | |
| 48 | |
| 49 :ivar action: Action to be taken. | |
| 50 | |
| 51 :ivar action_text: The text value for the specified action, if any. | |
| 52 | |
| 53 :ivar conditions: A dictionary of conditions that specify when the action | |
| 54 should be taken. Each item in the dictionary represents the name and | |
| 55 value (or a list of multiple values, if applicable) of a condition. | |
| 56 """ | |
| 57 | |
| 58 def __init__(self, action=None, action_text=None, conditions=None): | |
| 59 self.action = action | |
| 60 self.action_text = action_text | |
| 61 self.conditions = conditions or {} | |
| 62 | |
| 63 # Name of the current enclosing tag (used to validate the schema). | |
| 64 self.current_tag = RULE | |
| 65 | |
| 66 def validateStartTag(self, tag, parent): | |
| 67 """Verify parent of the start tag.""" | |
| 68 if self.current_tag != parent: | |
| 69 raise InvalidLifecycleConfigError( | |
| 70 'Invalid tag %s found inside %s tag' % (tag, self.current_tag)) | |
| 71 | |
| 72 def validateEndTag(self, tag): | |
| 73 """Verify end tag against the start tag.""" | |
| 74 if tag != self.current_tag: | |
| 75 raise InvalidLifecycleConfigError( | |
| 76 'Mismatched start and end tags (%s/%s)' % | |
| 77 (self.current_tag, tag)) | |
| 78 | |
| 79 def startElement(self, name, attrs, connection): | |
| 80 if name == ACTION: | |
| 81 self.validateStartTag(name, RULE) | |
| 82 elif name in LEGAL_ACTIONS: | |
| 83 self.validateStartTag(name, ACTION) | |
| 84 # Verify there is only one action tag in the rule. | |
| 85 if self.action is not None: | |
| 86 raise InvalidLifecycleConfigError( | |
| 87 'Only one action tag is allowed in each rule') | |
| 88 self.action = name | |
| 89 elif name == CONDITION: | |
| 90 self.validateStartTag(name, RULE) | |
| 91 elif name in LEGAL_CONDITIONS: | |
| 92 self.validateStartTag(name, CONDITION) | |
| 93 # Verify there is no duplicate conditions. | |
| 94 if (name in self.conditions and | |
| 95 name not in LEGAL_REPEATABLE_CONDITIONS): | |
| 96 raise InvalidLifecycleConfigError( | |
| 97 'Found duplicate non-repeatable conditions %s' % name) | |
| 98 else: | |
| 99 raise InvalidLifecycleConfigError('Unsupported tag ' + name) | |
| 100 self.current_tag = name | |
| 101 | |
| 102 def endElement(self, name, value, connection): | |
| 103 self.validateEndTag(name) | |
| 104 if name == RULE: | |
| 105 # We have to validate the rule after it is fully populated because | |
| 106 # the action and condition elements could be in any order. | |
| 107 self.validate() | |
| 108 elif name == ACTION: | |
| 109 self.current_tag = RULE | |
| 110 elif name in LEGAL_ACTIONS: | |
| 111 if name == SET_STORAGE_CLASS and value is not None: | |
| 112 self.action_text = value.strip() | |
| 113 self.current_tag = ACTION | |
| 114 elif name == CONDITION: | |
| 115 self.current_tag = RULE | |
| 116 elif name in LEGAL_CONDITIONS: | |
| 117 self.current_tag = CONDITION | |
| 118 # Some conditions specify a list of values. | |
| 119 if name in LEGAL_REPEATABLE_CONDITIONS: | |
| 120 if name not in self.conditions: | |
| 121 self.conditions[name] = [] | |
| 122 self.conditions[name].append(value.strip()) | |
| 123 else: | |
| 124 self.conditions[name] = value.strip() | |
| 125 else: | |
| 126 raise InvalidLifecycleConfigError('Unsupported end tag ' + name) | |
| 127 | |
| 128 def validate(self): | |
| 129 """Validate the rule.""" | |
| 130 if not self.action: | |
| 131 raise InvalidLifecycleConfigError( | |
| 132 'No action was specified in the rule') | |
| 133 if not self.conditions: | |
| 134 raise InvalidLifecycleConfigError( | |
| 135 'No condition was specified for action %s' % self.action) | |
| 136 | |
| 137 def to_xml(self): | |
| 138 """Convert the rule into XML string representation.""" | |
| 139 s = ['<' + RULE + '>'] | |
| 140 s.append('<' + ACTION + '>') | |
| 141 if self.action_text: | |
| 142 s.extend(['<' + self.action + '>', | |
| 143 self.action_text, | |
| 144 '</' + self.action + '>']) | |
| 145 else: | |
| 146 s.append('<' + self.action + '/>') | |
| 147 s.append('</' + ACTION + '>') | |
| 148 s.append('<' + CONDITION + '>') | |
| 149 for condition_name in self.conditions: | |
| 150 if condition_name not in LEGAL_CONDITIONS: | |
| 151 continue | |
| 152 if condition_name in LEGAL_REPEATABLE_CONDITIONS: | |
| 153 condition_values = self.conditions[condition_name] | |
| 154 else: | |
| 155 # Wrap condition value in a list, allowing us to iterate over | |
| 156 # all condition values using the same logic. | |
| 157 condition_values = [self.conditions[condition_name]] | |
| 158 for condition_value in condition_values: | |
| 159 s.extend(['<' + condition_name + '>', | |
| 160 condition_value, | |
| 161 '</' + condition_name + '>']) | |
| 162 s.append('</' + CONDITION + '>') | |
| 163 s.append('</' + RULE + '>') | |
| 164 return ''.join(s) | |
| 165 | |
| 166 class LifecycleConfig(list): | |
| 167 """ | |
| 168 A container of rules associated with a lifecycle configuration. | |
| 169 """ | |
| 170 | |
| 171 def __init__(self): | |
| 172 # Track if root tag has been seen. | |
| 173 self.has_root_tag = False | |
| 174 | |
| 175 def startElement(self, name, attrs, connection): | |
| 176 if name == LIFECYCLE_CONFIG: | |
| 177 if self.has_root_tag: | |
| 178 raise InvalidLifecycleConfigError( | |
| 179 'Only one root tag is allowed in the XML') | |
| 180 self.has_root_tag = True | |
| 181 elif name == RULE: | |
| 182 if not self.has_root_tag: | |
| 183 raise InvalidLifecycleConfigError('Invalid root tag ' + name) | |
| 184 rule = Rule() | |
| 185 self.append(rule) | |
| 186 return rule | |
| 187 else: | |
| 188 raise InvalidLifecycleConfigError('Unsupported tag ' + name) | |
| 189 | |
| 190 def endElement(self, name, value, connection): | |
| 191 if name == LIFECYCLE_CONFIG: | |
| 192 pass | |
| 193 else: | |
| 194 raise InvalidLifecycleConfigError('Unsupported end tag ' + name) | |
| 195 | |
| 196 def to_xml(self): | |
| 197 """Convert LifecycleConfig object into XML string representation.""" | |
| 198 s = ['<?xml version="1.0" encoding="UTF-8"?>'] | |
| 199 s.append('<' + LIFECYCLE_CONFIG + '>') | |
| 200 for rule in self: | |
| 201 s.append(rule.to_xml()) | |
| 202 s.append('</' + LIFECYCLE_CONFIG + '>') | |
| 203 return ''.join(s) | |
| 204 | |
| 205 def add_rule(self, action, action_text, conditions): | |
| 206 """ | |
| 207 Add a rule to this Lifecycle configuration. This only adds the rule to | |
| 208 the local copy. To install the new rule(s) on the bucket, you need to | |
| 209 pass this Lifecycle config object to the configure_lifecycle method of | |
| 210 the Bucket object. | |
| 211 | |
| 212 :type action: str | |
| 213 :param action: Action to be taken. | |
| 214 | |
| 215 :type action_text: str | |
| 216 :param action_text: Value for the specified action. | |
| 217 | |
| 218 :type conditions: dict | |
| 219 :param conditions: A dictionary of conditions that specify when the | |
| 220 action should be taken. Each item in the dictionary represents the name | |
| 221 and value of a condition. | |
| 222 """ | |
| 223 rule = Rule(action, action_text, conditions) | |
| 224 self.append(rule) |
