Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(636)

Unified Diff: third_party/gsutil/third_party/boto/boto/gs/lifecycle.py

Issue 1377933002: [catapult] - Copy Telemetry's gsutilz over to third_party. (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: Rename to gsutil. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/gsutil/third_party/boto/boto/gs/lifecycle.py
diff --git a/third_party/gsutil/third_party/boto/boto/gs/lifecycle.py b/third_party/gsutil/third_party/boto/boto/gs/lifecycle.py
new file mode 100644
index 0000000000000000000000000000000000000000..65f7d65d4e956ecd386de3a1cba4868d3572e574
--- /dev/null
+++ b/third_party/gsutil/third_party/boto/boto/gs/lifecycle.py
@@ -0,0 +1,227 @@
+# Copyright 2013 Google Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+from boto.exception import InvalidLifecycleConfigError
+
+# Relevant tags for the lifecycle configuration XML document.
+LIFECYCLE_CONFIG = 'LifecycleConfiguration'
+RULE = 'Rule'
+ACTION = 'Action'
+DELETE = 'Delete'
+CONDITION = 'Condition'
+AGE = 'Age'
+CREATED_BEFORE = 'CreatedBefore'
+NUM_NEWER_VERSIONS = 'NumberOfNewerVersions'
+IS_LIVE = 'IsLive'
+
+# List of all action elements.
+LEGAL_ACTIONS = [DELETE]
+# List of all action parameter elements.
+LEGAL_ACTION_PARAMS = []
+# List of all condition elements.
+LEGAL_CONDITIONS = [AGE, CREATED_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE]
+# Dictionary mapping actions to supported action parameters for each action.
+LEGAL_ACTION_ACTION_PARAMS = {
+ DELETE: [],
+}
+
+class Rule(object):
+ """
+ A lifecycle rule for a bucket.
+
+ :ivar action: Action to be taken.
+
+ :ivar action_params: A dictionary of action specific parameters. Each item
+ in the dictionary represents the name and value of an action parameter.
+
+ :ivar conditions: A dictionary of conditions that specify when the action
+ should be taken. Each item in the dictionary represents the name and value
+ of a condition.
+ """
+
+ def __init__(self, action=None, action_params=None, conditions=None):
+ self.action = action
+ self.action_params = action_params or {}
+ self.conditions = conditions or {}
+
+ # Name of the current enclosing tag (used to validate the schema).
+ self.current_tag = RULE
+
+ def validateStartTag(self, tag, parent):
+ """Verify parent of the start tag."""
+ if self.current_tag != parent:
+ raise InvalidLifecycleConfigError(
+ 'Invalid tag %s found inside %s tag' % (tag, self.current_tag))
+
+ def validateEndTag(self, tag):
+ """Verify end tag against the start tag."""
+ if tag != self.current_tag:
+ raise InvalidLifecycleConfigError(
+ 'Mismatched start and end tags (%s/%s)' %
+ (self.current_tag, tag))
+
+ def startElement(self, name, attrs, connection):
+ if name == ACTION:
+ self.validateStartTag(name, RULE)
+ elif name in LEGAL_ACTIONS:
+ self.validateStartTag(name, ACTION)
+ # Verify there is only one action tag in the rule.
+ if self.action is not None:
+ raise InvalidLifecycleConfigError(
+ 'Only one action tag is allowed in each rule')
+ self.action = name
+ elif name in LEGAL_ACTION_PARAMS:
+ # Make sure this tag is found in an action tag.
+ if self.current_tag not in LEGAL_ACTIONS:
+ raise InvalidLifecycleConfigError(
+ 'Tag %s found outside of action' % name)
+ # Make sure this tag is allowed for the current action tag.
+ if name not in LEGAL_ACTION_ACTION_PARAMS[self.action]:
+ raise InvalidLifecycleConfigError(
+ 'Tag %s not allowed in action %s' % (name, self.action))
+ elif name == CONDITION:
+ self.validateStartTag(name, RULE)
+ elif name in LEGAL_CONDITIONS:
+ self.validateStartTag(name, CONDITION)
+ # Verify there is no duplicate conditions.
+ if name in self.conditions:
+ raise InvalidLifecycleConfigError(
+ 'Found duplicate conditions %s' % name)
+ else:
+ raise InvalidLifecycleConfigError('Unsupported tag ' + name)
+ self.current_tag = name
+
+ def endElement(self, name, value, connection):
+ self.validateEndTag(name)
+ if name == RULE:
+ # We have to validate the rule after it is fully populated because
+ # the action and condition elements could be in any order.
+ self.validate()
+ elif name == ACTION:
+ self.current_tag = RULE
+ elif name in LEGAL_ACTIONS:
+ self.current_tag = ACTION
+ elif name in LEGAL_ACTION_PARAMS:
+ self.current_tag = self.action
+ # Add the action parameter name and value to the dictionary.
+ self.action_params[name] = value.strip()
+ elif name == CONDITION:
+ self.current_tag = RULE
+ elif name in LEGAL_CONDITIONS:
+ self.current_tag = CONDITION
+ # Add the condition name and value to the dictionary.
+ self.conditions[name] = value.strip()
+ else:
+ raise InvalidLifecycleConfigError('Unsupported end tag ' + name)
+
+ def validate(self):
+ """Validate the rule."""
+ if not self.action:
+ raise InvalidLifecycleConfigError(
+ 'No action was specified in the rule')
+ if not self.conditions:
+ raise InvalidLifecycleConfigError(
+ 'No condition was specified for action %s' % self.action)
+
+ def to_xml(self):
+ """Convert the rule into XML string representation."""
+ s = '<' + RULE + '>'
+ s += '<' + ACTION + '>'
+ if self.action_params:
+ s += '<' + self.action + '>'
+ for param in LEGAL_ACTION_PARAMS:
+ if param in self.action_params:
+ s += ('<' + param + '>' + self.action_params[param] + '</'
+ + param + '>')
+ s += '</' + self.action + '>'
+ else:
+ s += '<' + self.action + '/>'
+ s += '</' + ACTION + '>'
+ s += '<' + CONDITION + '>'
+ for condition in LEGAL_CONDITIONS:
+ if condition in self.conditions:
+ s += ('<' + condition + '>' + self.conditions[condition] + '</'
+ + condition + '>')
+ s += '</' + CONDITION + '>'
+ s += '</' + RULE + '>'
+ return s
+
+class LifecycleConfig(list):
+ """
+ A container of rules associated with a lifecycle configuration.
+ """
+
+ def __init__(self):
+ # Track if root tag has been seen.
+ self.has_root_tag = False
+
+ def startElement(self, name, attrs, connection):
+ if name == LIFECYCLE_CONFIG:
+ if self.has_root_tag:
+ raise InvalidLifecycleConfigError(
+ 'Only one root tag is allowed in the XML')
+ self.has_root_tag = True
+ elif name == RULE:
+ if not self.has_root_tag:
+ raise InvalidLifecycleConfigError('Invalid root tag ' + name)
+ rule = Rule()
+ self.append(rule)
+ return rule
+ else:
+ raise InvalidLifecycleConfigError('Unsupported tag ' + name)
+
+ def endElement(self, name, value, connection):
+ if name == LIFECYCLE_CONFIG:
+ pass
+ else:
+ raise InvalidLifecycleConfigError('Unsupported end tag ' + name)
+
+ def to_xml(self):
+ """Convert LifecycleConfig object into XML string representation."""
+ s = '<?xml version="1.0" encoding="UTF-8"?>'
+ s += '<' + LIFECYCLE_CONFIG + '>'
+ for rule in self:
+ s += rule.to_xml()
+ s += '</' + LIFECYCLE_CONFIG + '>'
+ return s
+
+ def add_rule(self, action, action_params, conditions):
+ """
+ Add a rule to this Lifecycle configuration. This only adds the rule to
+ the local copy. To install the new rule(s) on the bucket, you need to
+ pass this Lifecycle config object to the configure_lifecycle method of
+ the Bucket object.
+
+ :type action: str
+ :param action: Action to be taken.
+
+ :type action_params: dict
+ :param action_params: A dictionary of action specific parameters. Each
+ item in the dictionary represents the name and value of an action
+ parameter.
+
+ :type conditions: dict
+ :param conditions: A dictionary of conditions that specify when the
+ action should be taken. Each item in the dictionary represents the name
+ and value of a condition.
+ """
+ rule = Rule(action, action_params, conditions)
+ self.append(rule)

Powered by Google App Engine
This is Rietveld 408576698